bigywater.tech
Docker · 16

buildx 多平台镜像:manifest list 里放了什么

多平台镜像的“一个 tag 多个平台”是怎么实现的?这篇构建一个 amd64 + arm64 的镜像,拆开 docker save 出来的索引,看里面到底放了哪些 manifest,哪些是构建附带的证明,并实测跨架构运行要慢多少。

4 个 manifest
两平台镜像的索引里:2 个平台 manifest + 2 个 attestation manifest
unknown/unknown
attestation manifest 在索引里的平台标记,注解 vnd.docker.reference.type = attestation-manifest
496 vs 366 ms
amd64(模拟)与 arm64(原生)跑同一个 3 亿次整数运算循环

怎么构建

实测 · 本机执行输出
  --platform linux/arm64:退出码 0,用时 650 ms
  --platform linux/amd64,linux/arm64 --load:退出码 0,用时 419 ms;成功

用 FROM scratch 加两份交叉编译好的静态二进制,Dockerfile 里用 ${TARGETARCH} 选文件,docker buildx build --platform linux/amd64,linux/arm64 --load 就把两个平台一次构建出来并加载到本地。这个 Docker 用的是 containerd 镜像存储,所以多平台镜像可以直接加载;经典的存储驱动下不行(本文没有测)。

索引里有什么

实测 · 本机执行输出
  index.json:1 个条目,mediaType = application/vnd.oci.image.index.v1+json
  顶层索引(mediaType = application/vnd.oci.image.index.v1+json)里有 4 个 manifest:
    linux/amd64 digest=d4d001400e4d… size=480 注解={}
    linux/arm64 digest=b29f7d7637cd… size=480 注解={}
    unknown/unknown digest=8e0a1ae62f1b… size=835 注解={'vnd.docker.reference.digest': 'sha256:d4d001400e4d75e5bb2cd36c4c101c54d', 'vnd.docker.reference.type': 'attestation-manifest'}
    unknown/unknown digest=7d3f8f43cf43… size=835 注解={'vnd.docker.reference.digest': 'sha256:b29f7d7637cd5c82e8571a2b1dcc4e543', 'vnd.docker.reference.type': 'attestation-manifest'}

读 docker save 出来的 index.json,它指向一个 OCI index,里面有 4 个条目:两个真正的平台 manifest(linux/amd64、linux/arm64,各 480 字节),和两个平台标成 unknown/unknown 的条目——它们的注解 vnd.docker.reference.type 是 attestation-manifest,指向对应平台的 manifest,是 BuildKit 默认附带的构建证明。看到 unknown/unknown 别当成多余的平台。

跨架构运行

实测 · 本机执行输出
  --platform linux/arm64:我是 linux/arm64 的二进制
  --platform linux/amd64:我是 linux/amd64 的二进制

在 arm64 的 Docker Desktop 上 --platform linux/amd64 也能运行同一个 tag,输出确认是 amd64 的二进制。纯整数的紧循环,模拟只慢了约 1.36 倍(496 ms 对 366 ms);这只是一种负载,具体是哪种翻译技术在起作用,我没有查。

inspect 只显示当前平台

实测 · 本机执行输出
  linux/arm64:3 次取最快 366 ms
  linux/amd64:3 次取最快 496 ms

docker image inspect 对多平台镜像只显示宿主机平台那一份(arm64),不代表镜像只有这一个平台。

没测的

实测 · 本机执行输出
  bwlab-c11-single:Os=linux Architecture=arm64 Size=3702660
  bwlab-c11-multi:Os=linux Architecture=arm64 Size=3702660

推送到仓库后的 manifest list 形态、--provenance=false 去掉证明、构建 amd64 版本时的模拟构建速度,都没有在本文实验。

分步演示

多平台镜像
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Docker Desktop(Engine 29.8.2,容器跑在 Docker Desktop 自带的 Linux 虚拟机里,内核与宿主机的 macOS 不同);镜像为 linux/arm64;需要看虚拟机内部时用特权容器 + nsenter;计时用 time / date +%s%N,数字每次运行会有小幅抖动。镜像用 FROM scratch + Go 静态二进制(CGO_ENABLED=0 交叉编译两份),所以不需要从 Docker Hub 拉基础镜像;索引内容用 docker save 导出后用 Python 读取;两次构建都命中了缓存,构建用时不具可比性;跨架构性能只测了一种整数循环,每个平台 3 次取最快;实验后已删除所有镜像
    • 没有验证:真实基础镜像(如 alpine)的多平台构建、构建时 RUN 在模拟平台上的速度、推送到 registry 后的索引、provenance / SBOM 的内容、Rosetta 与 QEMU 的选择与影响、Windows 平台镜像
    京ICP备2026067502号-1京公网安备11010502063487号