Docker跨架构部署实操

发布于:2025-07-08 ⋅ 阅读:(36) ⋅ 点赞:(0)

需求场景

python项目,开发环境以及可供测试的环境为X86架构下的LINUX服务器,但正式环境需要部署在ARM架构下的麒麟服务器,且正式环境后续可能会长时间处于断网状态,需要一份跨架构的部署方案。

解决思路

在 X86 上打包、在 ARM(麒麟 Linux)上运行,最大的难点就在于二进制兼容性——X86 编译出的可执行文件(无论是用 PyInstaller 还是其它方式)都无法直接在 ARM 上跑。下面分别说一下两种方案的利弊,供你决策时参考:

Docker 多架构镜像

优点
  1. 环境一致性
    通过 Dockerfile 明确声明基础镜像、系统包、Python 版本、依赖库版本等,避免「开发机能跑、线上机跑不起来」的坑。
  2. 多平台支持
    利用 Docker 官方提供的多架构基础镜像(如 python:3.x-slim),配合 Docker Buildx,可以一次性编译出适用于 amd64、arm64 等多种架构的镜像。
  3. 零交叉编译成本
    你不需要在 X86 上搞复杂的交叉编译工具链,只要在 Dockerfile 里写好指令,Buildx 就能在后台(或远程 builder)帮你做。
缺点
  1. 镜像体积
    即便用 slimalpine,完整 Python 运行时的镜像通常也在几十 MB 以上,如果部署环境对镜像大小有苛刻要求,可能需要你做深度瘦身。
  2. 运维依赖
    线上机器要跑 Docker;如果你的正式环境是「只能跑二进制、不能装 Docker」的受限环境,则不可用。

PyInstaller 打包成单文件可执行

优点
  1. 无须容器化
    只要拿到一个可执行文件,线上直接部署即可,不用关心 Docker 或容器平台。
  2. 单文件交付
    如果团队习惯把交付物放到文件服务器、再由运维拷贝到目标机器,这种方式更简单。
缺点
  1. 必须在 ARM 机器上打包
    PyInstaller 打出来的 ELF 可执行档会绑定打包时的 CPU 架构;在 X86 上编的程序跑不了 ARM。你要么在真正的 ARM Kirin 机器上打包,要么在 X86 上借助 QEMU + chroot/交叉编译环境才能打出 ARM 二进制,配置成本高。
  2. 依赖隐蔽
    Python 动态库、C 扩展包、系统库等都要一一收集到打包目录,版本不对就可能「缺少依赖」或「符号找不到」。

Docker 多架构镜像

下面给出一个 从 X86 机器打包,到 脱网 ARM 麒麟服务器离线部署 的全流程示例。假设你的项目结构和文件列表如下:

myapp/
├── langou_model_mainfun.py
├── langou_model_dataprocessing.py
├── langou_model_function.py
├── langou_model_param.py
├── requirements.txt
└── .dockerignore

1. 在 X86 机上准备项目

  1. 创建 .dockerignore(减少镜像体积)
    myapp/ 下新建 .dockerignore,内容示例:

    __pycache__/
    *.pyc
    .git
    .idea
    *.log
    
  2. 编写 Dockerfile
    myapp/ 下新建 Dockerfile,内容如下:

    FROM docker.1ms.run/library/python:3.9-slim
    
    WORKDIR /app
    
    # 复制依赖并安装
    RUN pip3 install --no-cache-dir torch torchvision torchaudio -i https://pypi.tuna.tsinghua.edu.cn/simple
    COPY requirements.txt .
    RUN pip install --no-cache-dir -r requirements.txt
    
    # 复制所有源码文件
    COPY . .
    
    # (可选)健康检查:确保至少能 import 主模块
    HEALTHCHECK --interval=30s --timeout=3s \
      CMD python -c "import langou_model_mainfun" || exit 1
    
    # 容器启动时执行主脚本
    CMD ["python", "langou_model_mainfun.py"]
    

2. 在 X86 机上启用 Buildx + QEMU

  1. 检查 Docker 版本 & Buildx
docker version
docker buildx version
  1. 注册 QEMU 模拟器(支持在本机模拟 ARM 构建,使用国内镜像)
docker run --rm --privileged docker.1ms.run/multiarch/qemu-user-static --reset -p yes
  1. 创建并切换到 buildx Builder
docker buildx create --name mybuilder --use --driver docker-container --driver-opt image=docker.1ms.run/moby/buildkit:buildx-stable-1

docker buildx inspect --bootstrap

3. 构建 ARM64 镜像并导出为离线包

myapp/ 目录下运行:

docker buildx build \
  --platform linux/arm64 \
  --tag myapp:arm64-v1.0 \
  --output type=docker,dest=./myapp_arm64_v1.0.tar \
  .
  • --platform linux/arm64:生成 ARM64 架构镜像
  • --output type=docker,dest=...tar:将镜像导出为 tar

执行完后,你会在 myapp/ 目录看到 myapp_arm64_v1.0.tar

4. 拷贝镜像包到服务器

假设你在开发机上生成了 myapp_arm64_v1.0.tar,用 scp、USB 或其他方式,把它放到服务器上的某个目录,比如 /opt/deploy/myapp/

# 在开发机上
scp myapp_arm64_v1.0.tar root@arm-server:/opt/deploy/myapp/

5. 在服务器上加载镜像

cd /opt/deploy/myapp/
docker load -i myapp_arm64_v1.0.tar

运行后你应该能看到类似:

Loaded image: myapp:arm64-v1.0

6. 运行容器

docker run 时指定 --restart 参数:

docker run -d \
  --name myapp \
  --restart always \
  -v /opt/deploy/myapp/conf:/app/conf:ro \
  -e SOME_ENV=foo \
  myapp:arm64-v1.0
  • --restart no (默认)容器退出后不重启
  • --restart on-failure[:max-retries]
  • --restart always 宿主机重启后始终重启容器
  • --restart unless-stopped 类似 always,但如果你手动 docker stop 过,就不会再自动重启

推荐使用 --restart unless-stopped,这样即使遇到异常也重启,但运维手动停过就不会被“顽固”重启。

7. 验证运行状态

docker ps
docker logs myapp
  • docker ps:查看容器是否在运行
  • docker logs myapp:查看启动日志,确认没有错误

Tip

  • 如果你不需要挂载任何外部文件,则直接:
docker run -d --name myapp myapp:arm64-v1.0

  • 要停止或删除容器:
docker stop myapp
docker rm myapp

网站公告

今日签到

点亮在社区的每一天
去签到