x86 机器上开发、ARM 服务器上上线,为每个架构单独构建一遍镜像太笨重。docker buildx 借助 QEMU 用户态仿真,一条命令就能产出多架构镜像。本文从环境准备讲到推送验证,覆盖私有仓库场景下的全部配置点。
为什么需要跨平台构建
常见做法是每个平台各构建一次,但当开发平台与目标平台不一致时,往往还得额外准备目标架构的编译环境。默认的 docker build 无法跨平台,需要 buildx 插件配合:Linux 内核通过 QEMU 用户态模式注册二进制转换处理程序,运行时动态翻译目标架构的二进制指令,效果等同于在本地仿真运行目标架构的程序,容器里的编译体验与原生几乎一致。
Buildx 能力清单
- 多平台构建:单条命令产出多个 CPU 架构的镜像。
- 构建缓存:支持本地与远程缓存,复用前次构建结果。
- 实验性功能:用 –platform 指定目标平台,用 –build-arg BUILDKIT_INLINE_CACHE=1 开启内联缓存。
- 并发构建:同时在多个节点构建多个镜像。
- 外部构建器:结合 QEMU,在一个架构上构建另一个架构的镜像。
- 镜像导出:输出 tar 文件,供没有 Docker 的环境使用。
启用 buildx 与 binfmt_misc
macOS/Windows 的 Docker Desktop 与 Linux deb/rpm 安装的 Docker 已内置 buildx,先确认命令可用:
docker buildx version
没有内置时,从 Docker buildx 项目的 release 页面(https://github.com/docker/buildx/releases/latest)下载对应平台的二进制文件,命名为 docker-buildx,放入插件目录并加执行权限:
mv docker-buildx ~/.docker/cli-plugins/
chmod +x ~/.docker/cli-plugins/docker-buildx
Docker for Linux 默认不支持构建 arm 架构镜像,跑一次 binfmt 容器开启该能力(Docker 桌面版默认已启用 binfmt_misc,可跳过;注意 Linux 内核需 4.x 以上,CentOS 7 默认 3.10 不满足):
[root@DevOps ~]# docker run --rm --privileged tonistiigi/binfmt:latest --install all
# 验证是 binfmt_misc 否开启:
[root@DevOps ~]# ls -al /proc/sys/fs/binfmt_misc

验证 qemu-arm 处理器已注册启用:
[root@DevOps ~]# cat /proc/sys/fs/binfmt_misc/qemu-arm
# 这表示 binfmt_misc 对象(在这里是 qemu-arm)是启用的
enabled
# 这是指定用于解释目标架构二进制文件的解释器。这里使用的是/usr/bin/qemu-arm
interpreter /usr/bin/qemu-arm
# 这是一组标志,它们指示了如何处理目标二进制文件。
flags: OCF
# 这个字段指示了在目标文件的哪个偏移量开始执行解释器。
offset 0
# 这个字段描述了目标文件的特征码,也就是一个标志序列,用于识别文件的格式。
magic 7f454c4601010100000000000000000002002800
# 这个字段定义了哪些部分是需要匹配的,哪些部分是通配符。
mask ffffffffffffff00fffffffffffffffffeffffff
创建多平台构建器
Docker 默认的构建器实例不支持同时指定多个 –platform,需要手动创建新实例。如果私有仓库是 http 且没有证书,创建时必须带 –driver-opt network=host 和 –config 两个参数,同时在 Docker 的 daemon.json 中加入 “insecure-registries” 配置。先准备 buildkitd.toml:
[root@DevOps ~]# vim /etc/buildkit/buildkitd.toml
debug = true
# insecure-entitlements allows insecure entitlements, disabled by default.
insecure-entitlements = [ "network.host", "security.insecure" ]
# optionally mirror configuration can be done by defining it as a registry.
[registry."私有仓库地址IP或者域名"]
http = true
insecure = true
创建名为 my-builder 的构建器并设为当前活动实例:
[root@DevOps ~]# docker buildx create --name my-builder --use --driver-opt network=host --config /etc/buildkit/buildkitd.toml
参数说明:–name 指定构建器名称;–use 创建后立即切换使用;–driver-opt network=host 让构建器进程使用宿主机网络命名空间,可访问宿主机网络资源;–config 指定构建器配置文件路径。
检查当前部署的构建器:
[root@DevOps ~]# docker buildx inspect

启动新构建器实例:
[root@DevOps ~]# docker buildx inspect my-builder --bootstrap

查看当前使用的构建器及其支持的 CPU 架构:
[root@DevOps ~]# docker buildx ls

构建并推送多平台镜像
用一个最简单的应用验证:基础镜像通过 –platform=$TARGETPLATFORM 指定平台,把 uname 结果写入文件并在启动时输出:
[root@DevOps ~]# vim Dockerfile
# 通过 --platform=$TARGETPLATFORM指定平台的Alpine 镜像作为基础
FROM --platform=$TARGETPLATFORM alpine
# 运行 uname 命令并将输出写入 os.txt 文件
RUN uname -a > /os.txt
# 设置容器启动时默认执行的命令
CMD cat /os.txt
推送前先登录私有镜像仓库:
[root@DevOps ~]# docker login <私有镜像仓库>
Username: 用户
Password: 密码
Login Succeeded
执行构建,用 –push 直接推送到仓库:
[root@DevOps ~]# docker buildx build --platform linux/arm64,linux/amd64 -t 私有仓库地址/public/REPOSITORY[:TAG] --push .

到私有仓库的项目页面确认同一标签下存在多个架构的镜像:

验证镜像与注意事项
用 imagetools 探查已推送到远程仓库的镜像:
[root@DevOps ~]# docker buildx imagetools inspect 私有仓库地址/public/REPOSITORY[:TAG]

本机启用了 binfmt_misc 后,可以直接按 sha256 值拉取任意架构的镜像做本地测试:
[root@DevOps ~]# docker run -it --rm 私有仓库地址/public/demo:v1.0@sha256:xxx


- 多平台镜像无法同时使用 –load 载入本地,只能 –push 推送或输出到目录,这是构建器层面的限制。
- QEMU 模拟执行编译速度明显慢于原生,重编译类镜像建议挂真实架构的远程节点做 builder。
- http 私有仓库需要 buildkitd.toml、driver-opt、daemon.json 三处配置同时到位,缺一处就会在推送阶段报证书或网络错误。
- CentOS 7 一类老内核环境升级内核后再用 arm 构建,否则 binfmt 注册成功也无法正常执行。















暂无评论内容