惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Engineering at Meta
Engineering at Meta
博客园_首页
H
Help Net Security
WordPress大学
WordPress大学
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
罗磊的独立博客
博客园 - 三生石上(FineUI控件)
B
Blog
I
InfoQ
SecWiki News
SecWiki News
T
Tailwind CSS Blog
Spread Privacy
Spread Privacy
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
V
Vulnerabilities – Threatpost
N
Netflix TechBlog - Medium
P
Palo Alto Networks Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Vercel News
Vercel News
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
K
Kaspersky official blog
M
MIT News - Artificial intelligence
S
Schneier on Security
T
Threat Research - Cisco Blogs
F
Fortinet All Blogs
Cyberwarzone
Cyberwarzone
Scott Helme
Scott Helme
aimingoo的专栏
aimingoo的专栏
Martin Fowler
Martin Fowler
MyScale Blog
MyScale Blog
The Cloudflare Blog
Recent Announcements
Recent Announcements
Security Latest
Security Latest
G
GRAHAM CLULEY
IT之家
IT之家
Y
Y Combinator Blog
The Last Watchdog
The Last Watchdog
腾讯CDC
Google DeepMind News
Google DeepMind News
V
V2EX
S
Securelist
TaoSecurity Blog
TaoSecurity Blog
B
Blog RSS Feed
S
SegmentFault 最新的问题
博客园 - 叶小钗
P
Proofpoint News Feed
云风的 BLOG
云风的 BLOG
Project Zero
Project Zero
G
Google Developers Blog
Google DeepMind News
Google DeepMind News
F
Full Disclosure

🕵️‍♂️匿名运维栈

Uv 完全指南 - 🕵️‍♂️匿名运维栈 Python typing类型注解完全指南 - 🕵️‍♂️匿名运维栈 2025:大语言模型(LLM)之年 - 🕵️‍♂️匿名运维栈 AI 代码指南 [转载] - 🕵️‍♂️匿名运维栈 Lsky Pro + Typora 图床搭建 DNS 域名解析工具 - 🕵️‍♂️匿名运维栈 Ubuntu DNS解析失败排查记录:EasyConnect VPN劫持问题完全解析 - 🕵️‍♂️匿名运维栈 高效休息法:学习效率提升的科学指南 - 🕵️‍♂️匿名运维栈 Claude Code 子代理(Subagents)完全学习指南 - 🕵️‍♂️匿名运维栈
Docker构建多架构镜像 - 🕵️‍♂️匿名运维栈
nwnusun · 2026-01-06 · via 🕵️‍♂️匿名运维栈

共计 6771 个字符,预计需要花费 17 分钟才能阅读完成。

随着 ARM 架构服务器的普及和容器化部署的发展, 我们经常需要为不同架构构建镜像。以前这个过程相当繁琐, 需要在不同架构的机器上分别构建。Docker 19.03 引入的 Buildx 插件彻底改变了这个局面, 让跨平台构建变得简单高效。

如果你的系统还没有安装 Docker, 可以使用这个一键安装脚本:

bash <(curl -sSL https://gitee.com/SuperManito/LinuxMirrors/raw/main/DockerInstallation.sh)

Docker 19.03 及以上版本通常已经内置了 Buildx 插件。首先检查当前是否已安装:

docker buildx version

如果能看到版本号输出, 说明已经安装, 可以跳过下面的安装步骤, 直接进入 "配置跨架构模拟环境" 部分。

这是官方推荐的安装方式, 可以自动接收安全更新:

# Debian/Ubuntu 系统
sudo apt-get update
sudo apt-get install docker-buildx-plugin

# RHEL/CentOS 系统
sudo yum install docker-buildx-plugin

# Fedora 系统
sudo dnf install docker-buildx-plugin

Docker Desktop 用户: macOS 和 Windows 用户使用 Docker Desktop 时已经内置 Buildx, 无需额外安装。

从 Docker 官方 GitHub 仓库下载最新版 buildx(替换版本号和架构为你的实际情况):

wget https://github.com/docker/buildx/releases/download/v0.30.1/buildx-v0.30.1.linux-amd64

安装并配置二进制文件

# 创建插件目录(确保存在)sudo mkdir -p /usr/libexec/docker/cli-plugins/

# 移动二进制文件,添加执行权限
sudo mv docker-buildx /usr/libexec/docker/cli-plugins/docker-buildx
sudo chmod +x /usr/libexec/docker/cli-plugins/docker-buildx

# 验证文件权限
ls -l /usr/libexec/docker/cli-plugins/docker-buildx

让 Docker 默认使用 buildx 进行构建:

# 启用 buildx 为默认构建器
docker buildx install

# 验证安装
docker buildx version

macOS 和 Windows 的 Docker Desktop 已经内置了跨架构支持, 可以跳过这一步。Linux 用户需要手动配置 QEMU 模拟器:

docker run --privileged --rm tonistiigi/binfmt --install all

这个命令会安装 QEMU 模拟器并配置 binfmt_misc, 让系统能够识别和执行不同架构的二进制文件。

验证配置:

[root@centos ~]# ls -al /proc/sys/fs/binfmt_misc/
total 0
drwxr-xr-x 2 root root 0 Jan  6 11:17 .
dr-xr-xr-x 1 root root 0 Nov 20 09:23 ..
-rw-r--r-- 1 root root 0 Jan  6 11:17 qemu-aarch64
-rw-r--r-- 1 root root 0 Jan  6 11:17 qemu-arm
-rw-r--r-- 1 root root 0 Jan  6 11:17 qemu-loongarch64
-rw-r--r-- 1 root root 0 Jan  6 11:17 qemu-mips64
-rw-r--r-- 1 root root 0 Jan  6 11:17 qemu-mips64el
-rw-r--r-- 1 root root 0 Jan  6 11:17 qemu-ppc64le
-rw-r--r-- 1 root root 0 Jan  6 11:17 qemu-riscv64
-rw-r--r-- 1 root root 0 Jan  6 11:17 qemu-s390x
--w------- 1 root root 0 Jan  6 11:17 register
-rw-r--r-- 1 root root 0 Jan  6 11:17 status

能看到这些 qemu-* 文件就说明配置成功。

在多阶段构建中, 我们经常需要从中间阶段提取编译好的二进制文件。这里有个技巧。

先看一个简单的 Go 程序构建:

FROM golang:1.21 AS build
WORKDIR /app
RUN echo 'package main; import"fmt"; func main() { fmt.Println("Hello") }' > main.go
RUN CGO_ENABLED=0 go build -o myapp main.go

直接导出 build 阶段:

docker buildx build --target build --output ./test1 .

这样会把整个 golang:1.21 基础镜像的文件系统都导出来:

bad-output/
  ├── bin/           (bash, sh, 等系统命令)
  ├── usr/           (系统库和工具)
  ├── lib/           (系统库)
  ├── go/            (整个 Go 工具链,几百 MB)
  ├── app/
  │   └── myapp      ← 你真正想要的文件
  └── ... 还有更多系统文件

我们真正需要的只是那个小小的 myapp 可执行文件。

使用 FROM scratch 作为过滤层:

FROM golang:1.21 AS build
WORKDIR /app
RUN echo 'package main; import"fmt"; func main() { fmt.Println("Hello") }' > main.go
RUN CGO_ENABLED=0 go build -o myapp main.go

FROM scratch AS export
COPY --from=build /app/myapp /myapp

scratch 是 Docker 官方提供的空镜像, 它不是一个实际存在的镜像, 而是一个特殊的标记, 代表完全空的文件系统。通过它我们可以精确控制导出的内容:

docker buildx build --target export --output ./good-output .

这次输出目录就只有需要的文件了:

good-output/
  └── myapp          ← 完美!只有这一个文件

多阶段构建的意义在于: 构建阶段的所有内容 (Go 编译器、系统文件等) 仅用于编译, 不会进入最终输出。

如果需要组织更复杂的输出结构:

FROM golang:1.21 AS build
WORKDIR /app
RUN echo 'package main; import"fmt"; func main() { fmt.Println("Hello") }' > main.go
RUN CGO_ENABLED=0 go build -o myapp main.go

FROM scratch AS organized
COPY --from=build /app/myapp /bin/myapp
COPY --from=build /app/main.go /src/main.go

执行导出:

docker buildx build --target organized --output ./organized-output .

导出后会得到规范的目录结构:

organized-output/
  ├── bin/
  │   └── myapp
  └── src/
      └── main.go

这是 Buildx 最强大的功能。准备好 Dockerfile:

FROM golang:1.21 AS build
WORKDIR /app
RUN echo 'package main; import"fmt"; func main() { fmt.Println("Hello") }' > main.go
RUN CGO_ENABLED=0 go build -o myapp main.go

FROM scratch AS multi-arch
COPY --from=build /app/myapp /myapp

尝试执行多架构导出:

docker buildx build 
  --platform linux/amd64,linux/arm64 
  --target multi-arch 
  --output ./dist 
  .

你会遇到这个错误:

[root@centos sun]# docker buildx build 
>   --platform linux/amd64,linux/arm64 
>   --target multi-arch 
>   --output ./dist 
>   .
[+] Building 0.0s (0/0)                                                                             docker:default
ERROR: Multi-platform build is not supported for the docker driver.
Switch to a different driver, or turn on the containerd image store, and try again.
Learn more at https://docs.docker.com/go/build-multi-platform/

这是因为默认的 docker 驱动只能构建与宿主机架构一致的镜像, 多平台构建需要使用 docker-container 驱动。

# 创建构建器配置目录
mkdir -p /etc/docker/buildx

# 配置私有仓库(如果有的话)
cat > /etc/docker/buildx/config.toml << EOF
[registry."192.168.100.189"]
  http = true
  insecure = true
EOF

# 创建新的构建器
docker buildx create 
  --name multiarch-builder 
  --driver docker-container 
  --config /etc/docker/buildx/config.toml 
  --use

# 查看构建器状态
docker buildx ls

输出结果:

[root@centos sun]# docker buildx ls
NAME/NODE                DRIVER/ENDPOINT                   STATUS     BUILDKIT   PLATFORMS
multiarch-builder*       docker-container                                        
 _ multiarch-builder0    _ unix:///var/run/docker.sock   inactive              
default                  docker                                                  
 _ default               _ default                       running    v0.13.2    linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/amd64/v4, linux/386

注意 multiarch-builder 的状态是 inactive。这是因为 docker-container 驱动的构建器本质是一个后台运行的 BuildKit 容器, 创建后默认不会自动启动。

启动并初始化构建器:

docker buildx inspect multiarch-builder --bootstrap

同时确保 QEMU 模拟器已安装:

docker run --privileged --rm tonistiigi/binfmt --install all

安装输出:

[root@centos sun]# docker run --privileged --rm tonistiigi/binfmt --install all
Unable to find image 'tonistiigi/binfmt:latest' locally
latest: Pulling from tonistiigi/binfmt
f4700b809f99: Pull complete 
2adec5d296ac: Pull complete 
Digest: sha256:30cc9a4d03765acac9be2ed0afc23af1ad018aed2c28ea4be8c2eb9afe03fbd1
Status: Downloaded newer image for tonistiigi/binfmt:latest
installing: mips64 OK
installing: loong64 OK
installing: arm64 OK
installing: arm OK
installing: ppc64le OK
installing: riscv64 OK
installing: s390x OK
installing: mips64le OK
{
  "supported": [
    "linux/amd64",
    "linux/amd64/v2",
    "linux/amd64/v3",
    "linux/amd64/v4",
    "linux/arm64",
    "linux/riscv64",
    "linux/ppc64le",
    "linux/s390x",
    "linux/386",
    "linux/mips64le",
    "linux/mips64",
    "linux/loong64",
    "linux/arm/v7",
    ...
  ]
}

1. 导出到本地文件系统

现在重新执行多架构构建:

docker buildx build 
  --platform linux/amd64,linux/arm64 
  --target multi-arch 
  --output ./dist 
  .

输出结果:

[root@centos sun]# tree dist/
dist/
├── linux_amd64
│   └── myapp
└── linux_arm64
    └── myapp

这种方式适合需要手动分发二进制文件的场景。

2. 加载到本地 Docker(仅支持单架构)

注意:--load 只支持单架构构建。

构建 amd64 版本:

docker buildx build 
  --platform linux/amd64 
  -t myimage:amd64 
  --load 
  .

查看结果:

[root@centos sun]# docker images | grep myimage
myimage                                                         amd64                          dbeefa0220ea   7 minutes ago   2.54MB

构建 arm64 版本:

docker buildx build 
  --platform linux/arm64 
  -t myimage:arm64 
  --load 
  .

查看结果:

[root@centos sun]# docker images | grep myimage
myimage                                                         arm64                          1ad9de4d7e24   6 minutes ago   2.51MB
myimage                                                         amd64                          dbeefa0220ea   7 minutes ago   2.54MB

这种方式适合本地测试不同架构的镜像。

3. 推送到镜像仓库(支持多架构)

这是最常用的方式:

docker buildx build 
  --platform linux/amd64,linux/arm64 
  -t 192.168.100.189/test/myimage:v1 
  --push 
  .

一次推送就包含了两个架构的镜像。镜像仓库 (如 Harbor) 只会显示一个镜像条目, 但它实际上是一个 manifest list, 包含了多个架构的镜像索引。这是完全正常的现象。

4. 导出为 OCI 归档

docker buildx build 
  --platform linux/amd64,linux/arm64 
  -t myimage:v3 
  --output type=oci,dest=./myimage.tar 
  .

# 查看导出的文件
ls -lh myimage.tar

这种方式适合离线分发或迁移场景。

  1. 版本要求: 确保 Docker 版本不低于 19.03。现代版本已经默认集成 Buildx, 无需额外配置。
  2. 构建器状态管理: docker-container 驱动的构建器是个独立容器, 重启系统后需要重新 bootstrap。
  3. 缓存优化: Buildx 的缓存机制很强大, 合理利用可以大幅提升构建速度。推荐使用 --cache-from--cache-to 参数。
  4. 私有仓库配置: 如果使用私有仓库, 一定要在创建构建器时配置好 config.toml, 否则推送时会失败。
  5. 架构选择: 不是所有基础镜像都支持所有架构。构建前最好先确认基础镜像支持你需要的目标架构。
  6. 性能考虑: 跨架构构建需要 QEMU 模拟, 速度会比原生构建慢很多。生产环境建议使用原生架构的 CI/CD runner。
  7. 安全更新: 生产环境优先通过包管理器安装 Buildx, 可以自动接收安全补丁。

Buildx 让多架构镜像构建变得简单可控。掌握了这些技巧, 无论是导出构建产物还是构建多平台镜像, 都能游刃有余。建议在实际项目中多实践, 找到最适合自己场景的工作流。