Docker 多架构镜像构建方案实施指南

Docker 多架构镜像构建方案实施指南

  • [Docker 多架构镜像构建方案实施指南](#Docker 多架构镜像构建方案实施指南)
    • 一、背景与需求
      • [1.1 原有方案](#1.1 原有方案)
      • [1.2 目标方案](#1.2 目标方案)
    • 二、技术方案
      • [2.1 核心技术:Docker Buildx](#2.1 核心技术:Docker Buildx)
      • [2.2 构建策略](#2.2 构建策略)
      • [2.3 输出格式](#2.3 输出格式)
    • 三、实施过程
      • [3.1 环境要求](#3.1 环境要求)
      • [3.2 创建构建脚本](#3.2 创建构建脚本)
      • [3.3 安装 QEMU 模拟器](#3.3 安装 QEMU 模拟器)
    • 四、问题排查与解决
      • [4.1 问题一:单架构构建时 docker driver 不支持导出](#4.1 问题一:单架构构建时 docker driver 不支持导出)
      • [4.2 问题二:跨架构构建报 exec format error](#4.2 问题二:跨架构构建报 exec format error)
      • [4.3 问题三:Buildx 无法访问 Docker Hub(核心问题)](#4.3 问题三:Buildx 无法访问 Docker Hub(核心问题))
    • 五、最终测试结果
    • 六、脚本使用指南
      • [6.1 基本用法](#6.1 基本用法)
      • [6.2 导出离线 tar 包](#6.2 导出离线 tar 包)
      • [6.3 推送到私有仓库](#6.3 推送到私有仓库)
      • [6.4 输出文件说明](#6.4 输出文件说明)
      • [6.5 目标机器导入](#6.5 目标机器导入)
    • [七、常见问题 FAQ](#七、常见问题 FAQ)
      • [Q1: 首次运行多架构构建很慢?](#Q1: 首次运行多架构构建很慢?)
      • [Q2: 如何更新镜像加速器地址?](#Q2: 如何更新镜像加速器地址?)
      • [Q3: 如何清理构建缓存?](#Q3: 如何清理构建缓存?)
      • [Q4: 多架构包比单架构包小?](#Q4: 多架构包比单架构包小?)
    • 八、相关文件
    • 九、参考资料

Docker 多架构镜像构建方案实施指南

创建时间: 2025-01-10

项目: 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 环境要求

bash 复制代码
# 检查 Docker 版本(需要 19.03+)
docker version
# 实际版本: 29.1.4

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

3.2 创建构建脚本

创建 docker_build.sh,主要功能:

bash 复制代码
# 参数解析
--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:

bash 复制代码
# 安装 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 方式:

bash 复制代码
# 单架构构建
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 二进制文件。

解决方案

bash 复制代码
# 安装 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 独立容器网络 独立缓存,需重新拉取

关键区别:

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

验证步骤

bash 复制代码
# 检查宿主机是否能访问 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 配置文件

bash 复制代码
mkdir -p ~/.docker/buildx

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

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

bash 复制代码
# 删除旧的 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 基本用法

bash 复制代码
# 查看帮助
./docker_build.sh --help

6.2 导出离线 tar 包

bash 复制代码
# 导出多架构包(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 推送到私有仓库

bash 复制代码
# 推送到默认仓库 (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 目标机器导入

bash 复制代码
# 导入镜像
docker load < registration_info_<版本>_multiarch.tar

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

七、常见问题 FAQ

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

首次运行需要:

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

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

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

编辑配置文件:

bash 复制代码
vim ~/.docker/buildx/buildkitd.toml

然后重建 builder:

bash 复制代码
docker buildx rm multiarch
# 下次运行脚本会自动重建

Q3: 如何清理构建缓存?

bash 复制代码
# 清理 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 镜像构建文件

九、参考资料

相关推荐
云雾J视界9 小时前
从Boost的设计哲学到工业实践:解锁下一代AI中间件架构的密码
c++·人工智能·中间件·架构·stackoverflow·boost
暴躁的鱼9 小时前
docker运行可登录的gerrit容器
运维·docker·容器
赵文宇(温玉)9 小时前
Docker与VM的差异与最佳场景
docker·容器·eureka
wangbing11259 小时前
平台介绍-开放API后台微服务
数据库·微服务·架构
techzhi9 小时前
docker compose和docker-compose的区别
运维·docker·容器
jasnet_u9 小时前
SpringBoot3.x+SpringCloudAlibaba2023+JDK17微服务基础框架搭建
微服务·云原生·架构
alonewolf_999 小时前
MySQL 架构与SQL执行全流程深度解析
sql·mysql·架构
一条咸鱼_SaltyFish10 小时前
[Day16] Bug 排查记录:若依框架二次开发中的经验与教训 contract-security-ruoyi
java·开发语言·经验分享·微服务·架构·bug·开源软件
幻云201010 小时前
Next.js 之道:从全栈思维到架构实战
开发语言·javascript·架构