一、背景
需要在 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 一键恢复脚本
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/registerdocker 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 验证
docker buildx build --builder arm64-builder \
--platform linux/amd64,linux/arm64 \
-t registry.example.com/my-app:latest --push .构建了一个具备多依赖的 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
docker restart buildx_buildkit_arm64-builder0
docker buildx inspect --bootstrap arm64-builderdocker 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
简记。







