Docker多架构镜像构建全过程

 更新时间:2026年01月13日 08:59:17   作者:techzhi  
文章介绍了如何使用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 tardocker load < image.tar
多架构导出OCI tardocker load < image.tar
推送仓库Registrydocker 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 <addr>   # 私有仓库地址(默认: 192.168.50.32)
--platform <p>      # 目标平台: amd64, arm64, all(默认: all)
--version <ver>     # 镜像版本(默认: 时间戳)
--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 builddocker宿主机网络使用宿主机缓存
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 输出文件说明

命令输出文件格式
--saveimages/registration_info_<版本>_multiarch.tarOCI
--save --platform amd64images/registration_info_<版本>_amd64.tarDocker
--save --platform arm64images/registration_info_<版本>_arm64.tarDocker

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.tomlBuildKit 镜像加速器配置
Dockerfile镜像构建文件

参考资料:

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Docker容器实战之镜像仓库

    Docker容器实战之镜像仓库

    这篇文章主要介绍了Docker容器实战之镜像仓库,文章通过Docker Hub为例,讲解关于镜像仓库的使用,需要的小伙伴可以参考一下
    2022-05-05
  • 解决Mac下 docker 无法 ping 通宿主机的问题

    解决Mac下 docker 无法 ping 通宿主机的问题

    这篇文章主要介绍了解决Mac下 docker 无法 ping 通宿主机的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • Docker部署mysql远程连接 解决2003的问题

    Docker部署mysql远程连接 解决2003的问题

    这篇文章主要介绍了Docker部署mysql远程连接 解决2003错误的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-03-03
  • docker compose部署jenkins过程详解

    docker compose部署jenkins过程详解

    Jenkins是开源CI/CD工具,支持自动化构建、测试、部署,具备插件扩展、分布式构建、多版本控制等特性,适用于持续集成、持续交付及自动化测试,显著提升开发效率与软件质量,适合各类项目规模使用
    2025-09-09
  • docker报错"no space left on device"问题及解决方案

    docker报错"no space left on device&qu

    文章说明因Docker根目录空间不足导致的问题,解决方案为迁移至更大空间目录,步骤包括检查磁盘使用、关闭Docker、创建新目录、复制数据、修改配置文件路径并重启服务,以确保数据安全和配置正确
    2025-09-09
  • Docker 部署Go的两种基础镜像的实现

    Docker 部署Go的两种基础镜像的实现

    这篇文章主要介绍了Docker 部署Go的两种基础镜像的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-04-04
  • docker容器里安装ssh的具体步骤

    docker容器里安装ssh的具体步骤

    本篇文章主要介绍了docker容器里安装ssh的具体步骤,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • Docker容器间通信与外网通信的操作

    Docker容器间通信与外网通信的操作

    这篇文章主要介绍了Docker容器间通信与外网通信的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-03-03
  • docker如何部署etcd集群

    docker如何部署etcd集群

    这篇文章主要介绍了docker如何部署etcd集群问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • docker pull镜像失败问题解决方法

    docker pull镜像失败问题解决方法

    在使用Docker拉取镜像时可能会遇到超时失败的问题,通常由网络问题导致,本文介绍了两种解决方法:更改镜像加速地址和添加DNS配置,这些措施可以帮助改善与Docker Hub的连接,提高拉取镜像的成功率,如果问题依旧,请参考更多相关资料或寻求专业帮助
    2024-09-09

最新评论