Docker buildx 实现跨架构构建与多架构镜像

💡 原文中文,约10600字,阅读约需26分钟。
📝

内容提要

本文介绍如何在arm64构建机上为amd64生产环境构建多架构Docker镜像。核心方案是使用buildx配合QEMU/binfmt_misc模拟跨架构执行,通过manifest list实现同一tag对应多架构,并自建私有Registry分发。文章详细演示了安装配置、手工合并manifest、buildx自动构建流程,并记录了镜像存储切换、builder配置等踩坑经验。

🔎

延伸解读

QEMU模拟的性能代价与适用场景

文章明确指出,QEMU用户态模拟的性能比真实环境慢5~20倍,因此适合CI/CD中偶尔的跨架构构建,但不适合长期以模拟方式运行服务。这意味着,如果生产环境需要持续运行跨架构容器,应优先考虑原生架构的构建机或使用多节点builder进行原生构建,而非依赖模拟。

镜像存储切换的注意事项

开启containerd镜像存储后,Docker会切换镜像格式,导致原有镜像不可见,正在运行的容器也会失效。因此,操作前需先关闭相关容器,并做好备份或迁移准备。回退配置并重启Docker即可恢复原有镜像,但切换期间的服务中断需提前规划。

docker-container builder的缓存隔离

使用docker-container driver创建的builder,其构建缓存和镜像与Docker本身相互独立,容器删除即缓存丢失。在CI场景中,建议使用--cache-to和--cache-from将缓存导出到外部后端(如registry),以便下次构建复用,减少QEMU模拟带来的耗时。

Q&A

如何在arm64构建机上构建amd64架构的Docker镜像?

可以使用Docker buildx配合QEMU/binfmt_misc实现跨架构构建。首先安装docker-buildx-plugin,然后运行`docker run --privileged --rm tonistiigi/binfmt --install linux/amd64`注册模拟器,最后使用`docker buildx build --platform linux/amd64,linux/arm64 -t <镜像名> . --push`构建并推送多架构镜像。

QEMU用户态模拟的性能如何?适合长期运行服务吗?

QEMU用户态模拟的性能比真实环境慢5~20倍,对于CI/CD中偶尔的跨架构构建来说完全够用,但不适合长期以模拟方式运行服务。

binfmt_misc在跨架构运行中起什么作用?

binfmt_misc是Linux内核的机制,允许注册规则,当执行文件头部匹配特定特征时,内核将文件交给指定的解释器(如QEMU)执行。在跨架构场景中,tonistiigi/binfmt将qemu-x86_64等模拟器注册进内核,使容器能透明运行跨架构镜像。

如何手工制作一个多架构镜像并推送到私有仓库?

首先分别拉取不同平台的镜像并打上不同标签,然后推送到私有仓库。接着使用`docker manifest create --insecure <目标tag> <镜像1> <镜像2>`合并为manifest list,最后用`docker manifest push --insecure <目标tag>`推送。

使用buildx构建多架构镜像时,docker driver报错不支持多平台构建,如何解决?

有两种解决方法:一是开启containerd镜像存储,在/etc/docker/daemon.json中设置`"features": {"containerd-snapshotter": true}`并重启Docker;二是创建使用docker-container driver的builder,例如`docker buildx create --name multi-arch --driver docker-container --bootstrap --use`。

docker-container driver的builder有什么特点?

docker-container driver会在独立容器中运行BuildKit服务,其构建缓存和镜像与Docker本身相互独立。构建缓存保存在builder容器内部,容器删除即丢失,但可以通过--cache-to/--cache-from导出到外部后端。此外,builder支持多节点,可将构建分发到对应架构的节点原生执行,避免QEMU模拟。

🏷️

标签

➡️

继续阅读