登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  软件教程

Docker Buildx 怎样构建多架构镜像

来源:17golang原创

时间:2026-10-15 01:56:45 271浏览 收藏

当一台开发机是 Apple Silicon,而线上节点还有 amd64 时,镜像“能构建”并不等于“两个架构都能拉取”。这篇文章用 Docker Buildx 固定一个镜像标签,同时构建 linux/amd64 和 linux/arm64,再把结果推送到仓库,让不同节点按自身架构获取对应镜像。

官方地址:https://docs.docker.com/build/building/multi-platform/

你需要一个可推送的镜像仓库,并完成 Docker 登录。本文示例中的仓库名使用占位符,不代表真实账号或仓库。

先确定最终要看到什么

成功结果有三个特征:构建命令明确写出两个平台;构建结果使用 --push 写入远程仓库;同一个标签下能看到一个镜像索引以及 linux/amd64、linux/arm64 两个平台条目。

不要把本地 docker images 中只出现一个架构的镜像,当成多架构发布已经完成。默认 Docker Engine 的本地镜像存储并不适合直接加载多平台结果,远程仓库才是本文的验收位置。

第一步:准备 Builder 和镜像标签

打开 Docker Desktop 的 Builds 或 Builder 管理入口,先确认当前 Builder 状态为可用。命令行也可以直接查看:

# 查看当前 Buildx builder、节点状态和可用平台
docker buildx ls

# 创建一个隔离的容器驱动 builder,并切换到它
docker buildx create --name multiarch-builder --driver docker-container --use

# 启动 builder,提前暴露平台支持与初始化错误
docker buildx inspect --bootstrap

把镜像标签先固定下来,例如 registry.example/team/demo:1.0.0。真实使用时替换成你有推送权限的仓库地址;不要把密码、Token 或个人路径写进命令。

Buildx Builder 和 linux amd64 arm64 平台选择的原创界面说明图
图1:Buildx 平台选择与镜像标签的原创操作示意图,不是实际 Docker 截图。

第二步:检查 Dockerfile 是否锁死了宿主架构

如果 Dockerfile 只是安装脚本或解释型程序,通常可以直接让基础镜像跟随目标平台。若包含编译步骤,可以利用 BuildKit 自动提供的 BUILDPLATFORM 和 TARGETPLATFORM,把构建工具运行在构建机平台,把产物编译到目标平台。

# 让编译器阶段运行在 builder 原生平台,减少不必要的模拟
FROM --platform=$BUILDPLATFORM golang:1.23-alpine AS build

# 这两个参数由 BuildKit 注入,用于区分构建平台和目标平台
ARG BUILDPLATFORM
ARG TARGETPLATFORM
WORKDIR /src
COPY . .

# 示例只展示平台参数传递;真实项目应在这里执行可复现的构建命令
RUN echo "build=$BUILDPLATFORM target=$TARGETPLATFORM" > /platform.txt

# 最终阶段不要硬编码 linux/amd64,让 --platform 决定基础镜像
FROM alpine:3.20
COPY --from=build /platform.txt /platform.txt

重点是不要在所有 FROM 后面随手写死 linux/amd64。这种写法会让 arm64 构建仍然拿到 amd64 基础层,最终表现为拉取或运行阶段的架构不匹配。

第三步:在构建界面中选择两个平台

在 Docker Desktop 的构建配置中,将 Platforms 设为 linux/amd64 和 linux/arm64,Image tag 填入刚才固定的版本标签。若使用命令行,对应参数是一个逗号分隔列表:

# 明确声明两个 Linux 目标平台,并给结果打固定版本标签
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  --tag registry.example/team/demo:1.0.0 \
  .

这里的 --platform 不只是筛选下载地址,它决定了没有单独指定平台的 FROM 指令将使用哪个目标平台,也决定最终输出需要包含哪些架构。

第四步:用 Push 保存多平台结果

多架构结果不能只依赖本地加载。将输出动作改为推送,并确保前面已经登录仓库:

# 登录目标仓库;凭据由 Docker 凭据存储处理,不写进脚本参数
docker login registry.example

# 构建两个平台并直接推送 manifest list 与各平台镜像
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  --tag registry.example/team/demo:1.0.0 \
  --push \
  .

在结果验收型流程里,看到构建日志结束只是中间状态。真正的完成点是仓库收到同一标签下的镜像索引与两个平台的镜像清单。--push 相当于选择 registry 输出;不要同时把它理解成“把两个架构都加载到本地 Docker Engine”。

第五步:核对标签和平台条目

打开仓库的镜像标签详情,或使用 Buildx 的元数据工具查看同一个标签。为了避免把真实仓库信息写进文章,下面的结果字段只作为核对形状:

# 读取远程标签的 manifest 信息,确认同一标签包含多个平台
docker buildx imagetools inspect registry.example/team/demo:1.0.0

# 预期重点观察这两个平台,而不是只看本机架构
# linux/amd64
# linux/arm64

界面上应能看到一个 Image index 或 manifest list,以及两个平台子项。digest 每次构建都可能不同,验收重点是标签、平台和推送状态三者是否同时存在。

镜像仓库中 manifest list 和 amd64 arm64 平台条目的原创结果说明图
图2:仓库结果页展示 manifest list 与两个平台条目的原创结果示意图,不是线上仓库截图。

遇到失败时按这四个位置修正

  1. Builder 不支持目标平台:先运行 docker buildx inspect --bootstrap,确认节点列出了目标平台;不要只看 Docker 客户端版本。
  2. 构建很慢:QEMU 模拟容易上手,但编译、压缩等 CPU 密集任务可能明显变慢。可以改用多个原生节点,或在多阶段构建中做交叉编译。
  3. 推送被拒绝:检查 docker login 的仓库域名、镜像命名空间和权限。认证失败和 Dockerfile 平台问题是两类故障,不要混在一起排查。
  4. 误用 --load:单平台结果适合加载到本地;多平台发布应优先使用 --push。如果必须在本机测试,分别指定一个平台构建后再加载。

最后留下可复用的发布清单

  • Builder 已启动,并能识别目标平台。
  • Dockerfile 没有把最终基础镜像硬编码成宿主架构。
  • --platform 同时包含 linux/amd64 与 linux/arm64。
  • 标签带有明确版本,不用浮动的临时标签验收。
  • 命令使用 --push,仓库结果显示 manifest list 和两个平台条目。

如果你的目标只是让本机启动一个镜像,单平台 --load 会更直接;如果目标是让不同架构节点共享一个版本标签,就按本文的 Buildx、--platform、--push 和仓库平台结果四处一起确认。

常见问题

为什么构建成功但 arm64 节点拉不到镜像?

常见原因是只构建了宿主架构,或使用了 --load 而没有推送多平台索引。先检查构建命令是否列出 arm64,再看远程标签是否真的包含该平台。

一定要手动安装 QEMU 吗?

不一定。Docker 官方的 BuildKit 环境通常会提供常见模拟能力;是否需要额外配置取决于 builder 环境和目标平台。对编译密集项目,原生节点或交叉编译通常更适合。

同一个标签能不能只推送其中一个平台?

可以单独构建一个平台,但这样标签的最终平台集合取决于推送策略和仓库现有清单。需要稳定的多架构交付时,应在一次明确的 Buildx 发布中列出完整平台集合。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>