文章介绍了如何使用DockerBuildx工具实现一次构建同时支持ARM64和AMD64平台的Docker镜像,并详细描述了构建过程、技术方案和问题排查,最终,通过脚本使用指南和常见问题解答,帮助用户更好地理解和使用该工具

  • 项目:cust-cont (自定义容器服务)
  • 目标:实现一次构建同时支持 ARM64 和 AMD64 平台的 Docker 镜像

一、背景与需求

1.1 原有方案

项目原有两个独立的构建脚本:

脚本 用途 构建命令
docker_build_arm.sh 构建 ARM 镜像 docker build
docker_build_x86.sh 构建 x86 镜像 docker build –platform linux/amd64

痛点

  • 每次发版需要分别执行两个脚本
  • 生成两个独立的 tar 包,管理成本高
  • 无法生成统一的多架构镜像

1.2 目标方案

实现一个统一的构建脚本 docker_build.sh,支持:

  • 一次构建生成多架构镜像(ARM64 + AMD64)
  • 支持推送到私有仓库或导出离线 tar 包
  • 通过参数灵活控制构建行为

二、技术方案

2.1 核心技术:Docker Buildx

Docker Buildx 是 Docker 官方的多架构构建工具,基于 BuildKit 实现。

架构原理

                         ┌─ linux/amd64 镜像层
registration_info:v1.0 ──┤
                         └─ linux/arm64 镜像层

一个镜像 tag 包含多架构 manifest,部署时 Docker 自动选择对应架构。

2.2 构建策略

场景 Driver 说明
单架构构建 docker (默认) 使用本地 Docker daemon,可利用本地镜像缓存
多架构构建 docker-container 在独立 BuildKit 容器中构建,支持跨架构

2.3 输出格式

模式 格式 导入方式
单架构导出 Docker tar docker load < image.tar
多架构导出 OCI tar docker load < image.tar
推送仓库 Registry docker pull registry/image:tag

三、实施过程

3.1 环境要求

# 检查 Docker 版本(需要 19.03+)
docker version
# 实际版本: 29.1.4

# 检查 Buildx 是否可用
docker buildx version
# 实际版本: v0.30.1

3.2 创建构建脚本

创建 docker_build.sh,主要功能:

# 参数解析
--push              # 推送到私有仓库
--save              # 导出为离线 tar 包
--registry    # 私有仓库地址(默认: 192.168.50.32)
--platform 

# 目标平台: amd64, arm64, all(默认: all) --version # 镜像版本(默认: 时间戳) --skip-build # 跳过 Maven 构建

3.3 安装 QEMU 模拟器

在 x86 机器上构建 ARM 镜像需要 QEMU:

# 安装 ARM64 QEMU 模拟器
docker run --rm --privileged tonistiigi/binfmt --install arm64

# 验证支持的架构
# 输出: linux/amd64, linux/arm64, ...

四、问题排查与解决

4.1 问题一:单架构构建时 docker driver 不支持导出

现象

ERROR: Docker exporter is not supported for the docker driver.

原因

docker buildx build --output type=docker,dest=file.tar

在使用默认 docker driver 时不支持直接导出到文件。

解决方案

单架构导出时改用传统的 docker build + docker save 方式:

# 单架构构建
docker build --platform linux/amd64 -t image:tag .
docker save -o image.tar image:tag

4.2 问题二:跨架构构建报 exec format error

现象

exec /bin/sh: exec format error

原因

在 x86 机器上构建 ARM 镜像时,需要 QEMU 模拟器来执行 ARM 二进制文件。

解决方案

# 安装 QEMU
docker run --rm --privileged tonistiigi/binfmt --install arm64

4.3 问题三:Buildx 无法访问 Docker Hub(核心问题)

现象

ERROR: failed to do request: Head "https://registry-1.docker.io/v2/...":
dial tcp xxx:443: i/o timeout

原因分析

构建方式 Driver 网络环境 镜像缓存
docker build docker 宿主机网络 使用宿主机缓存
docker buildx (多架构) docker-container 独立容器网络 独立缓存,需重新拉取

关键区别:

  • 普通 docker build 使用宿主机的 Docker daemon,可以使用 /etc/docker/daemon.json 中配置的镜像加速器
  • Buildx docker-container driver 运行在独立的 BuildKit 容器中,有自己独立的网络和配置,不会自动使用宿主机的镜像加速器配置

验证步骤

# 检查宿主机是否能访问 Docker Hub
curl -s --connect-timeout 5 https://registry-1.docker.io/v2/
# 返回 UNAUTHORIZED 说明可以连接

# 查看宿主机镜像加速器配置
cat /etc/docker/daemon.json
# 已配置: docker.1ms.run, docker.xuanyuan.me

解决方案

步骤一:创建 BuildKit 配置文件

mkdir -p ~/.docker/buildx

cat > ~/.docker/buildx/buildkitd.toml << 'EOF'
[registry."docker.io"]
  mirrors = ["docker.1ms.run", "docker.xuanyuan.me"]
EOF

步骤二:创建使用该配置的 Builder

# 删除旧的 builder
docker buildx rm multiarch 2>/dev/null || true

# 创建新的 builder,关键参数:
# --driver-opt network=host  使用宿主机网络
# --config                   指定 buildkit 配置文件
docker buildx create 
  --name multiarch 
  --driver docker-container 
  --driver-opt network=host 
  --config ~/.docker/buildx/buildkitd.toml 
  --use

# 启动并验证
docker buildx inspect --bootstrap

验证配置生效

File#buildkitd.toml:
 > [registry]
 >   [registry."docker.io"]
 >     mirrors = ["docker.1ms.run", "docker.xuanyuan.me"]

五、最终测试结果

测试场景 命令 结果 输出
单架构 AMD64 --save --platform amd64 ✅ 成功 *_amd64.tar (300M)
单架构 ARM64 --save --platform arm64 ✅ 成功 *_arm64.tar (324M)
多架构 --save ✅ 成功 *_multiarch.tar (258M)

六、脚本使用指南

6.1 基本用法

# 查看帮助
./docker_build.sh --help

6.2 导出离线 tar 包

# 导出多架构包(ARM64 + AMD64)
./docker_build.sh --save

# 导出指定版本
./docker_build.sh --save --version 1.2.0

# 只导出 x86 架构
./docker_build.sh --save --platform amd64

# 只导出 ARM 架构
./docker_build.sh --save --platform arm64

# 跳过 Maven 构建(jar 包已存在时)
./docker_build.sh --save --skip-build

6.3 推送到私有仓库

# 推送到默认仓库 (192.168.50.32)
./docker_build.sh --push

# 推送到指定仓库
./docker_build.sh --push --registry 10.0.0.100

# 指定版本推送
./docker_build.sh --push --version 1.2.0

6.4 输出文件说明

命令 输出文件 格式
--save images/registration_info_<版本>_multiarch.tar OCI
--save --platform amd64 images/registration_info_<版本>_amd64.tar Docker
--save --platform arm64 images/registration_info_<版本>_arm64.tar Docker

6.5 目标机器导入

# 导入镜像
docker load < registration_info_<版本>_multiarch.tar

# 查看导入的镜像
docker images | grep registration_info

七、常见问题 FAQ

Q1: 首次运行多架构构建很慢?

首次运行需要:

  • 拉取 BuildKit 镜像 (moby/buildkit:buildx-stable-1)
  • 拉取基础镜像的多架构层

后续构建会使用缓存,速度会快很多。

Q2: 如何更新镜像加速器地址?

编辑配置文件:

vim ~/.docker/buildx/buildkitd.toml

然后重建 builder:

docker buildx rm multiarch
# 下次运行脚本会自动重建

Q3: 如何清理构建缓存?

# 清理 buildx 缓存
docker buildx prune

# 清理所有缓存(谨慎使用)
docker buildx prune -a

Q4: 多架构包比单架构包小?

是的,OCI 格式的多架构包使用了更高效的压缩和层去重,所以可能比两个单架构包加起来更小。

八、相关文件

文件 说明
docker_build.sh 多架构构建脚本
docker_build_arm.sh 原 ARM 构建脚本(保留)
docker_build_x86.sh 原 x86 构建脚本(保留)
~/.docker/buildx/buildkitd.toml BuildKit 镜像加速器配置
Dockerfile 镜像构建文件

参考资料:

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持5186建站网。

您可能感兴趣的文章:

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。