## 9.3 构建多种系统架构支持的 Docker 镜像 Docker 镜像可以支持多种系统架构,这意味着你可以在 `x86_64`、`arm64` 等不同架构的机器上运行同一个镜像。这是通过一个名为 "manifest list"(或称为 "fat manifest")的文件来实现的。 ### Manifest List 是什么? 为了理解多架构镜像的原理,我们需要先了解 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 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 buildx`,我们也可以直接操作 Manifest List 来手动组合不同架构的镜像。 `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 的详细信息,如上文所示。