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 | 独立容器网络 | 独立缓存,需重新拉取 |
关键区别:
- 普通
docker build使用宿主机的 Docker daemon,可以使用/etc/docker/daemon.json中配置的镜像加速器 - 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: 首次运行多架构构建很慢?
首次运行需要:
- 拉取 BuildKit 镜像 (
moby/buildkit:buildx-stable-1) - 拉取基础镜像的多架构层
后续构建会使用缓存,速度会快很多。
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 |
镜像构建文件 |