modify: aarch64 设备docker部署
This commit is contained in:
+56
-29
@@ -1,48 +1,75 @@
|
||||
# FROM debian:bookworm-slim AS builder
|
||||
# 架构参数:可选值 x86_64 或 aarch64
|
||||
ARG TARGETARCH=x86_64
|
||||
|
||||
FROM ubuntu:24.04 AS builder
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends ca-certificates tzdata && \
|
||||
ARG TARGETARCH
|
||||
|
||||
# 跳过 GPG 签名验证(兼容 BM1684 等系统时间不准的设备)
|
||||
RUN apt-get update -o Acquire::AllowInsecureRepositories=yes \
|
||||
-o Acquire::AllowDowngradeToInsecureRepositories=yes \
|
||||
--allow-unauthenticated 2>/dev/null || true && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
-o Acquire::AllowInsecureRepositories=yes \
|
||||
--allow-unauthenticated \
|
||||
ca-certificates tzdata 2>/dev/null || true && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY build/chongming /tmp/chongming
|
||||
|
||||
RUN mkdir -p /tmp/rootfs/app && \
|
||||
# === 临时目录 ===
|
||||
mkdir -p /tmp/rootfs/tmp && \
|
||||
chmod 1777 /tmp/rootfs/tmp && \
|
||||
# === 数据目录 ===
|
||||
mkdir -p /tmp/rootfs/app/data && \
|
||||
chmod 777 /tmp/rootfs/app/data && \
|
||||
# === 解释器目录 ===
|
||||
mkdir -p /tmp/rootfs/lib64 && \
|
||||
mkdir -p /tmp/rootfs/lib/x86_64-linux-gnu && \
|
||||
cp /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /tmp/rootfs/lib/x86_64-linux-gnu/ && \
|
||||
ln -s /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /tmp/rootfs/lib64/ld-linux-x86-64.so.2 && \
|
||||
# 构建最小 rootfs
|
||||
RUN \
|
||||
if [ "$TARGETARCH" = "aarch64" ]; then \
|
||||
LIB_PATH="/lib/aarch64-linux-gnu"; \
|
||||
LD_LINKER="/lib/ld-linux-aarch64.so.1"; \
|
||||
LD_LINKER_TARGET="/tmp/rootfs/lib/ld-linux-aarch64.so.1"; \
|
||||
else \
|
||||
LIB_PATH="/lib/x86_64-linux-gnu"; \
|
||||
LD_LINKER="/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2"; \
|
||||
LD_LINKER_TARGET="/tmp/rootfs/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2"; \
|
||||
fi && \
|
||||
mkdir -p /tmp/rootfs/app && \
|
||||
mkdir -p /tmp/rootfs/tmp && chmod 1777 /tmp/rootfs/tmp && \
|
||||
mkdir -p /tmp/rootfs/app/data && chmod 777 /tmp/rootfs/app/data && \
|
||||
# === aarch64 链接器路径特殊处理 ===
|
||||
if [ "$TARGETARCH" = "aarch64" ]; then \
|
||||
mkdir -p /tmp/rootfs/lib && \
|
||||
cp /lib/ld-linux-aarch64.so.1 /tmp/rootfs/lib/ && \
|
||||
mkdir -p /tmp/rootfs/lib64 && \
|
||||
ln -s /lib/ld-linux-aarch64.so.1 /tmp/rootfs/lib64/ld-linux-aarch64.so.1; \
|
||||
else \
|
||||
mkdir -p /tmp/rootfs/lib64 && \
|
||||
mkdir -p /tmp/rootfs${LIB_PATH} && \
|
||||
cp ${LIB_PATH}/ld-linux-x86-64.so.2 /tmp/rootfs${LIB_PATH}/ && \
|
||||
ln -s ${LIB_PATH}/ld-linux-x86-64.so.2 /tmp/rootfs/lib64/ld-linux-x86-64.so.2; \
|
||||
fi && \
|
||||
# === 依赖库 ===
|
||||
cp /lib/x86_64-linux-gnu/libdl.so.2 /tmp/rootfs/lib/x86_64-linux-gnu/ && \
|
||||
cp /lib/x86_64-linux-gnu/libz.so.1 /tmp/rootfs/lib/x86_64-linux-gnu/ && \
|
||||
cp /lib/x86_64-linux-gnu/libpthread.so.0 /tmp/rootfs/lib/x86_64-linux-gnu/ && \
|
||||
cp /lib/x86_64-linux-gnu/libc.so.6 /tmp/rootfs/lib/x86_64-linux-gnu/ && \
|
||||
cp /lib/x86_64-linux-gnu/librt.so.1 /tmp/rootfs/lib/x86_64-linux-gnu/ && \
|
||||
cp /lib/x86_64-linux-gnu/libm.so.6 /tmp/rootfs/lib/x86_64-linux-gnu/ && \
|
||||
cp /lib/x86_64-linux-gnu/libutil.so.1 /tmp/rootfs/lib/x86_64-linux-gnu/ && \
|
||||
cp /lib/x86_64-linux-gnu/libnss_dns.so.2 /tmp/rootfs/lib/x86_64-linux-gnu/ 2>/dev/null || true && \
|
||||
cp /lib/x86_64-linux-gnu/libnss_files.so.2 /tmp/rootfs/lib/x86_64-linux-gnu/ 2>/dev/null || true && \
|
||||
cp /lib/x86_64-linux-gnu/libresolv.so.2 /tmp/rootfs/lib/x86_64-linux-gnu/ 2>/dev/null || true && \
|
||||
mkdir -p /tmp/rootfs${LIB_PATH} && \
|
||||
cp ${LIB_PATH}/libdl.so.2 /tmp/rootfs${LIB_PATH}/ && \
|
||||
cp ${LIB_PATH}/libz.so.1 /tmp/rootfs${LIB_PATH}/ && \
|
||||
cp ${LIB_PATH}/libpthread.so.0 /tmp/rootfs${LIB_PATH}/ && \
|
||||
cp ${LIB_PATH}/libc.so.6 /tmp/rootfs${LIB_PATH}/ && \
|
||||
cp ${LIB_PATH}/librt.so.1 /tmp/rootfs${LIB_PATH}/ && \
|
||||
cp ${LIB_PATH}/libm.so.6 /tmp/rootfs${LIB_PATH}/ && \
|
||||
cp ${LIB_PATH}/libutil.so.1 /tmp/rootfs${LIB_PATH}/ && \
|
||||
cp ${LIB_PATH}/libnss_dns.so.2 /tmp/rootfs${LIB_PATH}/ 2>/dev/null || true && \
|
||||
cp ${LIB_PATH}/libnss_files.so.2 /tmp/rootfs${LIB_PATH}/ 2>/dev/null || true && \
|
||||
cp ${LIB_PATH}/libresolv.so.2 /tmp/rootfs${LIB_PATH}/ 2>/dev/null || true && \
|
||||
# === 时区数据 ===
|
||||
mkdir -p /tmp/rootfs/usr/share/zoneinfo && \
|
||||
cp -r /usr/share/zoneinfo/Asia /tmp/rootfs/usr/share/zoneinfo/ && \
|
||||
cp /usr/share/zoneinfo/UTC /tmp/rootfs/usr/share/zoneinfo/ && \
|
||||
cp -r /usr/share/zoneinfo/Asia /tmp/rootfs/usr/share/zoneinfo/ 2>/dev/null || true && \
|
||||
cp /usr/share/zoneinfo/UTC /tmp/rootfs/usr/share/zoneinfo/ 2>/dev/null || true && \
|
||||
# === 证书和 DNS ===
|
||||
mkdir -p /tmp/rootfs/etc/ssl/certs && \
|
||||
cp /etc/ssl/certs/ca-certificates.crt /tmp/rootfs/etc/ssl/certs/ && \
|
||||
cp /etc/ssl/certs/ca-certificates.crt /tmp/rootfs/etc/ssl/certs/ 2>/dev/null || true && \
|
||||
echo "hosts: files dns" > /tmp/rootfs/etc/nsswitch.conf && \
|
||||
# === /proc /sys /dev ===
|
||||
mkdir -p /tmp/rootfs/proc /tmp/rootfs/sys /tmp/rootfs/dev
|
||||
|
||||
FROM scratch
|
||||
|
||||
ARG TARGETARCH
|
||||
|
||||
COPY --from=builder /tmp/rootfs/ /
|
||||
|
||||
COPY build/chongming /app/chongming
|
||||
@@ -55,4 +82,4 @@ WORKDIR /app
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
CMD ["./chongming"]
|
||||
CMD ["./chongming"]
|
||||
|
||||
@@ -77,7 +77,7 @@ chongming/
|
||||
### 运行原理
|
||||
|
||||
开发时通过 `uv run serve` 直接启动 uvicon。
|
||||
打包后,`chongming` 可执行文件内嵌了经过混淆的引导程序,引导程序从加密的 Module-Bank 文件 (`app.mbank`, `plugins.mbank`) 中动态加载应用模块,同时从 SQLite VFS (`static.svfs`) 提供前端静态文件。所有 Python 业务代码不暴露与明文磁盘。
|
||||
打包后,`chongming` 可执行文件内嵌了经过混淆的引导程序,引导程序从加密的 Module-Bank 文件 (`app.mbank`, `plugins.mbank`) 中动态加载应用模块,同时从 SQLite VFS (`static.svfs`) 提供前端静态文件。所有 Python 业务代码不暴露于明文磁盘。
|
||||
|
||||
---
|
||||
|
||||
@@ -197,12 +197,23 @@ build/
|
||||
|
||||
## Docker 部署
|
||||
|
||||
Docker 镜像采用多角度构建 + `scratch` 基础镜像,真正做到最小化。
|
||||
Docker 镜像采用多阶段构建 + `scratch` 基础镜像,真正做到最小化。同时支持 **x86_64** 与 **aarch64 (ARM64)** 双架构。
|
||||
|
||||
### 构建镜像
|
||||
|
||||
```bash
|
||||
# 默认构建 x86_64 架构
|
||||
docker build -t chongming:latest .
|
||||
|
||||
# 在 ARM64 设备上构建
|
||||
docker build --build-arg TARGETARCH=aarch64 -t chongming:arm64 .
|
||||
|
||||
# 使用 Docker Buildx 构建多架构镜像(推送到仓库)
|
||||
docker buildx build \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--build-arg TARGETARCH \
|
||||
-t your-registry/chongming:latest \
|
||||
--push .
|
||||
```
|
||||
|
||||
### 执行部署脚本
|
||||
|
||||
@@ -67,6 +67,9 @@ host = "0.0.0.0"
|
||||
port = 8000
|
||||
reload = false
|
||||
workers = 4
|
||||
# 对于嵌入式设备(如 BM1684),建议启用环境变量覆盖:
|
||||
# docker run -e APP_WORKERS=2 ...
|
||||
# 可减少线程数,避免 "can't start new thread" 错误
|
||||
|
||||
[production.logging]
|
||||
backup_count = 5 # 最多保存 10 个日志文件
|
||||
|
||||
@@ -12,8 +12,25 @@ log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
||||
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||
|
||||
# 配置
|
||||
IMAGE="chongming:latest"
|
||||
# 检测架构
|
||||
ARCH=$(uname -m)
|
||||
case "$ARCH" in
|
||||
x86_64|amd64)
|
||||
DEFAULT_IMAGE="chongming:latest"
|
||||
ARCH_FLAG="x86_64"
|
||||
;;
|
||||
aarch64|arm64)
|
||||
DEFAULT_IMAGE="chongming:arm64"
|
||||
ARCH_FLAG="aarch64"
|
||||
;;
|
||||
*)
|
||||
log_error "不支持的架构: $ARCH"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# 配置:可通过环境变量覆盖镜像标签,例如: IMAGE=chongming:arm64 ./deploy.sh
|
||||
IMAGE="${IMAGE:-$DEFAULT_IMAGE}"
|
||||
CONTAINER="chongming"
|
||||
PORT=8000
|
||||
DATA_DIR="${HOME}/chongming-data"
|
||||
@@ -60,13 +77,27 @@ if ss -tlnp | grep -q ":${PORT}"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 根据架构设置默认 worker 数
|
||||
case "$ARCH" in
|
||||
aarch64|arm64)
|
||||
DEFAULT_WORKERS=2
|
||||
;;
|
||||
*)
|
||||
DEFAULT_WORKERS=4
|
||||
;;
|
||||
esac
|
||||
|
||||
# 4. 启动容器
|
||||
log_info "启动容器..."
|
||||
log_info "架构: $ARCH, workers: ${APP_WORKERS:-$DEFAULT_WORKERS}, 端口: $PORT"
|
||||
docker run -d \
|
||||
-p "$PORT:8000" \
|
||||
-v "$DATA_DIR/data:/app/data" \
|
||||
-v "$DATA_DIR/uploads:/app/uploads" \
|
||||
-v "$DATA_DIR/logs:/app/logs" \
|
||||
-e "APP_WORKERS=${APP_WORKERS:-$DEFAULT_WORKERS}" \
|
||||
--ulimit nproc=65535 \
|
||||
--ulimit nofile=65535 \
|
||||
--restart unless-stopped \
|
||||
--name "$CONTAINER" \
|
||||
"$IMAGE"
|
||||
@@ -92,4 +123,4 @@ else
|
||||
log_error "容器启动失败,查看日志:"
|
||||
docker logs "$CONTAINER" 2>/dev/null || true
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
+4
-1
@@ -4,6 +4,7 @@
|
||||
FastAPI chongming 示例
|
||||
主入口文件,适配 chongming 打包系统
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import platform
|
||||
from utils.launch import launch
|
||||
@@ -37,7 +38,9 @@ def app_run(app_config: dict, default_config: dict):
|
||||
# 打包环境强制禁用重载
|
||||
is_frozen = getattr(sys, "frozen", False)
|
||||
reload = False if is_frozen else server_config.get("reload", False)
|
||||
workers = server_config.get("workers", 4)
|
||||
# 支持通过环境变量 APP_WORKERS 覆盖 worker 数量(方便嵌入式设备调优)
|
||||
default_workers = server_config.get("workers", 4)
|
||||
workers = int(os.environ.get("APP_WORKERS", str(default_workers)))
|
||||
|
||||
# 显示启动信息
|
||||
env = app_config.get("env", "development")
|
||||
|
||||
@@ -302,7 +302,7 @@ async def init_database():
|
||||
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker
|
||||
|
||||
from ..app.core.config import get_config
|
||||
from ..app.task.dev_init_db import init_permission, dev_init_admin
|
||||
from ..app.task.dev_init_db import init_permission, init_default_roles, dev_init_admin
|
||||
|
||||
database = get_config()["database"]
|
||||
database_type = database["type"]
|
||||
@@ -333,6 +333,9 @@ async def init_database():
|
||||
async with async_session_maker() as session:
|
||||
# await UserService.create_user(session, "admin", "admin", is_superuser=True) # type: ignore
|
||||
await init_permission(session)
|
||||
# 再初始化默认角色及权限关联
|
||||
await init_default_roles(session)
|
||||
# 最后初始化管理员用户
|
||||
await dev_init_admin(session)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user