Files
docker_practice/buildx/multi-arch-images.md
2026-01-02 16:55:39 -08:00

121 lines
4.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 构建多种系统架构支持的 Docker 镜像
Docker 镜像可以支持多种系统架构这意味着你可以在 `x86_64``arm64` 等不同架构的机器上运行同一个镜像这是通过一个名为 "manifest list"或称为 "fat manifest"的文件来实现的
## Manifest List 是什么
Manifest list 是一个包含了多个指向不同架构镜像的 manifest 的文件当你拉取一个支持多架构的镜像时Docker 会自动根据你当前的系统架构选择并拉取对应的镜像
例如官方的 `hello-world` 镜像就支持多种架构你可以使用 `docker manifest inspect` 命令来查看它的 manifest list
```bash
$ docker manifest inspect hello-world
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"manifests": [
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 525,
"digest": "sha256:80852a401a974d9e923719a948cc5335a0a4435be8778b475844a7153a2382e5",
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 525,
"digest": "sha256:3adea81344be1724b383d501736c3852939b33b3903d02474373700b25e5d6e3",
"platform": {
"architecture": "arm",
"os": "linux",
"variant": "v5"
}
},
// ... more architectures
]
}
```
## 使用 `docker buildx` 构建多架构镜像
Docker 19.03+ 版本中`docker buildx` 是推荐的用于构建多架构镜像的工具它使用 `BuildKit` 作为后端可以大大简化构建过程
### 新建 `builder` 实例
首先你需要创建一个新的 `builder` 实例因为它支持同时为多个平台构建
```bash
$ docker buildx create --name mybuilder --use
$ docker buildx inspect --bootstrap
```
### 构建和推送
使用 `docker buildx build` 命令并指定 `--platform` 参数可以同时构建支持多种架构的镜像`--push` 参数会将构建好的镜像和 manifest list 推送到 Docker 仓库
```dockerfile
# Dockerfile
FROM --platform=$TARGETPLATFORM alpine
RUN uname -a > /os.txt
CMD cat /os.txt
```
```bash
$ docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t your-username/multi-arch-image . --push
```
构建完成后你就可以在不同架构的机器上拉取并运行 `your-username/multi-arch-image` 这个镜像了
### 架构相关的构建参数
`Dockerfile` 你可以使用一些预定义的构建参数来根据目标平台定制构建过程
* `TARGETPLATFORM`: 构建镜像的目标平台例如 `linux/amd64`
* `TARGETOS`: 目标平台的操作系统例如 `linux`
* `TARGETARCH`: 目标平台的架构例如 `amd64`
* `TARGETVARIANT`: 目标平台的变种例如 `v7`
* `BUILDPLATFORM`: 构建环境的平台
* `BUILDOS`: 构建环境的操作系统
* `BUILDARCH`: 构建环境的架构
* `BUILDVARIANT`: 构建环境的变种
例如你可以这样编写 `Dockerfile` 来拷贝特定架构的二进制文件
```dockerfile
FROM scratch
ARG TARGETOS
ARG TARGETARCH
COPY bin/dist-${TARGETOS}-${TARGETARCH} /dist
ENTRYPOINT ["/dist"]
```
## 使用 `docker manifest` (底层工具)
`docker manifest` 是一个更底层的命令可以用来创建检查和推送 manifest list虽然 `docker buildx` 在大多数情况下更方便但了解 `docker manifest` 仍然有助于理解其工作原理
### 创建 manifest list
```bash
# 首先,为每个架构构建并推送镜像
$ docker buildx build --platform linux/amd64 -t your-username/my-app:amd64 . --push
$ docker buildx build --platform linux/arm64 -t your-username/my-app:arm64 . --push
# 然后,创建一个 manifest list将它们组合在一起
$ docker manifest create your-username/my-app:latest \
--amend your-username/my-app:amd64 \
--amend your-username/my-app:arm64
# 最后,推送 manifest list
$ docker manifest push your-username/my-app:latest
```
### 检查 manifest list
你可以使用 `docker manifest inspect` 来查看一个 manifest list 的详细信息如上文所示