modify: aarch64 设备docker部署

This commit is contained in:
root
2026-04-30 16:26:50 +08:00
parent 072a59a169
commit 074414aeab
6 changed files with 114 additions and 36 deletions
+54 -27
View File
@@ -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 && \
# === 解释器目录 ===
# 构建最小 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 && \
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 && \
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
+13 -2
View File
@@ -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 .
```
### 执行部署脚本
+3
View File
@@ -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 个日志文件
+33 -2
View File
@@ -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"
+4 -1
View File
@@ -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")
+4 -1
View File
@@ -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)