CentOS7 x86_64 上构建 ARM64 Docker 镜像简记

发表于 1 天前  4 次阅读


文章目录

一、背景

需要在 CentOS 7.6(内核 3.10)x86_64 虚拟机上构建 ARM64 架构的 Docker 镜像。方案选用 Docker Buildx + QEMU 用户态模拟,对比了 binfmt_misc + qemu-user-static 和原生 ARM64 机器两条路,前者零硬件成本适合 CI/CD 场景。

环境概况:

  • 宿主机: Hyper-V 虚拟机, CentOS 7.6.1810, kernel 3.10.0
  • Docker 26.1.4, Buildx v0.14.1
  • QEMU 7.2.0 (qemu-aarch64-static)
  • 8 vCPU, 5.5GB RAM, 57GB 可用磁盘

二、踩坑与要点

**坑1: CentOS 7 kernel 3.10 不支持 binfmt_misc 的 F (fix binary) 标志。**

F 标志允许内核在注册解释器时直接打开二进制文件,容器内即使没有 qemu 也能用。普通 OC 标志要求容器 filesystem 内能访问解释器路径。

解决方案:`docker run` 时 bind mount qemu-static 二进制进去:

docker run --rm --platform linux/arm64 \
  -v /usr/bin/qemu-aarch64-static:/usr/bin/qemu-aarch64-static \
  your-image:tag

**坑2:BuildKit 容器网络隔离导致 Docker Hub 超时。**

docker-container 驱动的 BuildKit 运行在独立容器内,不走宿主 Docker daemon 的 registry-mirrors 配置。

解决方案:创建 buildkitd.toml 配置文件,指定镜像加速:

[registry."docker.io"]
  mirrors = ["https://docker.m.daocloud.io"]

创建 builder 时挂载配置:

docker buildx create --name arm64-builder \
  --driver docker-container \
  --config /etc/buildkit/buildkitd.toml \
  --platform linux/amd64,linux/arm64 --use

三、最终环境配置

3.1 binfmt 注册

mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
echo ':qemu-aarch64:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-aarch64-static:OC' > /proc/sys/fs/binfmt_misc/register

3.2 Builder 配置

docker buildx create --name arm64-builder --driver docker-container \
  --config /etc/buildkit/buildkitd.toml \
  --platform linux/amd64,linux/arm64 --use
docker buildx inspect --bootstrap arm64-builder

3.3 一键恢复脚本

将 `/usr/local/bin/arm64-build-recover.sh` 设为开机自启后,每次重启执行即可恢复全部环境:

#!/bin/bash
# ARM64 Build Environment Recovery
until docker info >/dev/null 2>&1; do sleep 1; done
if [ ! -f /proc/sys/fs/binfmt_misc/qemu-aarch64 ]; then
    mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
    echo ':qemu-aarch64:M::\x7fELF\x02\x01\x01\x00...:/usr/bin/qemu-aarch64-static:OC' > /proc/sys/fs/binfmt_misc/register
fi
docker buildx inspect --bootstrap arm64-builder

BuildKit 容器 restart policy 为 unless-stopped,Docker 启动后自动拉起。

四、本地镜像复用(免重新下载)

4.1 利用 BuildKit 缓存

BuildKit 会自动缓存中间层和 base image,再次构建时秒级完成:

# 首次构建(拉取 base image + npm install 依赖)
docker buildx build --builder arm64-builder --platform linux/arm64 \
  -t my-app:v1 --load .   # 耗时 ~2min

# 第二次(代码改动,依赖未变)
docker buildx build --builder arm64-builder --platform linux/arm64 \
  -t my-app:v2 --load .   # 耗时 ~3s,CACHED

输出中的 CACHED 标记表示复用已缓存层。

4.2 Docker 层缓存复用

已拉取的基础镜像和构建产物存储在本地,不会重复下载:

# 查看本地 ARM64 镜像
docker images --filter "reference=arm64*"

# 导出镜像实现离线分发
docker save arm64-demo-app:v1 | gzip > arm64-demo-app.tar.gz

# 另一台机器导入(无需网络)
docker load < arm64-demo-app.tar.gz

4.3 构建到本地不 push

使用 `--load` 参数直接将镜像加载到本地 Docker,不经过远程仓库:

docker buildx build --builder arm64-builder --platform linux/arm64 \
  -t my-image:local --load .

4.4 多平台同时构建

docker buildx build --builder arm64-builder \
  --platform linux/amd64,linux/arm64 \
  -t registry.example.com/my-app:latest --push .

五、Demo 验证

构建了一个具备多依赖的 Node.js 应用作为验证:

Dockerfile 特点:

  • 多阶段构建(builder + production)
  • 非 root 用户运行
  • HEALTHCHECK 健康检查
  • npm 使用 npmmirror 镜像源加速

应用依赖:express、axios、redis、winston,共 119 个包。

构建结果:

  • 镜像大小:139MB (基础层 + 119 个 npm 包)
  • 构建耗时:~60s(含 npm install)
  • 二次构建(代码更新,依赖不变):3s(全部 CACHED)

运行验证:

$ docker run --platform linux/arm64 -v /usr/bin/qemu-aarch64-static:/usr/bin/qemu-aarch64-static arm64-demo-app:v1
info: Server started on port 3000 arch=arm64

$ curl http://localhost:3000/health
{"uptime":3.97,"memory":{...},"arch":"arm64"}

架构确认为 arm64,应用正常运行。

六、重启机器或容器后恢复

机器重启后

运维同学已配置好:

  • Docker 已设为开机自启 (`systemctl enable docker`)
  • BuildKit 容器 restart policy 为 unless-stopped,Docker 启动后自动拉起

手动执行验证:

# 快速验证环境
/usr/local/bin/arm64-build-recover.sh

# 输出 "ARM64 Build Environment Ready" 即恢复成功

仅重启 BuildKit 容器

docker restart buildx_buildkit_arm64-builder0
docker buildx inspect --bootstrap arm64-builder

彻底重建 Builder

docker buildx rm arm64-builder
docker buildx create --name arm64-builder --driver docker-container \
  --config /etc/buildkit/buildkitd.toml \
  --platform linux/amd64,linux/arm64 --use
docker buildx inspect --bootstrap arm64-builder

简记。

本站文章基于国际协议BY-NA-SA 4.0协议共享;
如未特殊说明,本站文章皆为原创文章,请规范转载。

0

scanz个人博客