多阶段构建本身不直接解决多架构问题,它负责镜像瘦身和环境隔离;多架构打包靠的是 buildx + manifest list 机制。
多阶段构建本身不直接解决多架构问题,它负责镜像瘦身和环境隔离;多架构打包靠的是 buildx + manifest list 机制。两者结合,才能实现“一次写 dockerfile、一次命令、产出多个平台镜像”的效果。
多阶段构建是基础,负责每个架构下的镜像精简
你写的多阶段 Dockerfile(比如 Go 编译 + Alpine 运行)会在每个目标架构上独立执行一遍。也就是说,buildx 会为 linux/amd64 启动一个基于 golang:1.21 的构建阶段,再复制到 alpine 镜像;同时也会为 linux/arm64 做完全相同的事——只是底层运行在 ARM64 环境(或通过 QEMU 模拟)。最终每个平台得到的都是体积小、无编译器、只含可执行文件的干净镜像。
- 多阶段构建保证了每个架构镜像的“内容正确性”和“体积最小化”
- 它不关心平台,只关心指令逻辑;平台适配由 buildx 在运行时接管
- 你无需为 AMD64 写一套 Dockerfile、再为 ARM64 改一套——一份即可复用
buildx 是关键桥梁,让多阶段构建跑在不同架构上
标准 docker build 只能在本机架构下运行,而 buildx 扩展了构建能力:
- 通过
docker buildx create --use --name mybuilder创建支持多平台的构建器 - 借助 QEMU(通过
binfmt_misc注册)在 x86 机器上模拟 ARM64/ARMv7 环境,让多阶段构建过程也能在非原生平台执行 - 使用
--platform linux/amd64,linux/arm64,linux/arm/v7显式声明目标架构,buildx 会为每个平台分别执行完整的多阶段流程
manifest list 是最终封装,把多个单架构镜像聚合成一个逻辑镜像
buildx 完成各平台构建并推送到仓库后,会自动生成一个 manifest list(OCI index),它本身不存文件,只是一份“地图”:
- 记录每个平台镜像的 digest(如
sha256:abc...@linux/amd64) - 当用户执行
docker pull your/app:latest,Docker 客户端读取该清单,自动匹配本地 platform 并拉取对应镜像 - 离线部署时,你可以用
docker buildx build --load把所有平台镜像加载进本地 daemon,再用docker save -o all.tar $(docker images --format "{{.Repository}}:{{.Tag}}" | grep your/app)打包,或用docker manifest inspect辅助提取
一个典型工作流示例
假设你有一个 Go 项目,Dockerfile 已是标准多阶段写法:
- 运行:
docker buildx build --platform linux/amd64,linux/arm64 --push -t yourname/myapp:1.0 . - buildx 自动为两个平台分别执行:golang 编译 → 复制二进制 → Alpine 运行镜像生成
- 推送完成后,远程仓库中实际存在两个镜像(带不同 platform 标签)+ 一个 manifest list
- 后续任何架构的机器拉取
yourname/myapp:1.0,都会拿到适配自己的版本










