多个主机上的多平台 Docker 镜像

问题描述 投票:0回答:1

我面前有两台电脑,一台Linux/x86_64,一台MacOS/arm64(M2 Mac)。我想构建一个多平台 Docker 镜像。我想在一台计算机上为其自己的架构(例如 x86_64)启动构建过程,上传/推送构建的映像,然后可能将该映像拉到另一台计算机上,为该架构(arm64)构建,然后推送包含多个架构的合成图像。我正在解释 Docker 手册中的这一行:

当您运行支持多平台的镜像时,Docker 会自动选择与您的操作系统和架构相匹配的镜像。

意味着确实存在一个多平台图像实体,而不是通过清单松散链接的两个存储库中的两个图像。

我不想使用 QEMU 进行构建。我不想购买整个云构建器的东西。我想做的事情似乎很简单,但我似乎找不到any有关如何做到这一点的信息。所有信息都是关于在云中使用 QEMU 或本机构建器,以某种方式编排的。有没有办法遵循上面的简单方法?

docker multiplatform
1个回答
0
投票

意味着确实存在一个多平台图像实体,而不是通过清单松散链接的两个存储库中的两个图像。

这令人困惑或者可能不准确。注册表中的多平台镜像由清单列表或索引表示,它是一个包含清单列表的 json 结构(顾名思义)。这些清单均由摘要引用,并位于同一存储库中。最终结果如下:

OCI Media Type Diagram


您可以使用标准 docker 构建创建单个平台映像并将其推送到注册表。要构建多平台映像,对我来说最简单的选择是利用 buildkit 和 buildx,它在运行时默认利用 qemu:

docker buildx build --platform=linux/amd64,linux/arm64 -t $repo:$tag .

如果编译器通过 Dockerfile 中的一些其他选项支持它,您可以跳过 qemu 并利用交叉编译:

# syntax=docker/dockerfile:1

# --platform=$BUILDPLATFORM runs this step on the local architecture
FROM --platform=$BUILDPLATFORM ${base_image} as build
COPY . /src
WORKDIR /src
# builtin vars are exposed to the environment for the target to build
ARG TARGETOS
ARG TARGETARCH
# the make command would need to leverage the TARGETOS and TARGETARCH vars
RUN make app

# this step runs with the target architecture
FROM ${deploy_image} as release
# with only a copy step, and no run commands, there is no qemu involved
COPY --from=build /src/bin/app /usr/local/bin/app

第三个选项是单独构建每个映像,推送到注册表,然后创建引用这两个映像的清单列表。有一些工具可以做到这一点,但我不一定会将此称为简单的选择,因为很少有人这样做(您还要处理构建管道中的竞争条件)。

Docker 的内置工具是

docker manifest
,它具有创建和推送创建的清单的选项。它被标记为实验性的,因此取决于它可能意味着需要在未来的 docker 版本中修改脚本:

$ docker manifest --help

Usage:  docker manifest COMMAND

The **docker manifest** command has subcommands for managing image manifests and
manifest lists. A manifest list allows you to use one name to refer to the same image
built for multiple architectures.

To see help for a subcommand, use:

    docker manifest CMD --help

For full details on using docker manifest lists, see the registry v2 specification.

EXPERIMENTAL:
  docker manifest is an experimental feature.
  Experimental features provide early access to product functionality. These
  features may change between releases without warning, or can be removed from a
  future release. Learn more about experimental features in our documentation:
  https://docs.docker.com/go/experimental/

Commands:
  annotate    Add additional information to a local image manifest
  create      Create a local manifest list for annotating and pushing to a registry
  inspect     Display an image manifest, or manifest list
  push        Push a manifest list to a repository
  rm          Delete one or more manifest lists from local storage

Run 'docker manifest COMMAND --help' for more information on a command.

由于这可以完全在注册表上完成,因此还有其他不需要了解 docker 的工具可用。我知道的其中两个是 Google 的 Crane 和我自己的 regctl:

$ crane index append --help
This sub-command pushes an index based on an (optional) base index, with appended manifests.

The platform for appended manifests is inferred from the config file or omitted if that is infeasible.

Usage:
  crane index append [flags]

Examples:
 # Append a windows hello-world image to ubuntu, push to example.com/hello-world:weird
  crane index append ubuntu -m hello-world@sha256:87b9ca29151260634b95efb84d43b05335dc3ed36cc132e2b920dd1955342d20 -t example.com/hello-world:weird

  # Create an index from scratch for etcd.
  crane index append -m registry.k8s.io/etcd-amd64:3.4.9 -m registry.k8s.io/etcd-arm64:3.4.9 -t example.com/etcd

Flags:
      --docker-empty-base   If true, empty base index will have Docker media types instead of OCI
      --flatten             If true, appending an index will append each of its children rather than the index itself (default true)
  -h, --help                help for append
  -m, --manifest strings    References to manifests to append to the base index
  -t, --tag string          Tag to apply to resulting image

Global Flags:
      --allow-nondistributable-artifacts   Allow pushing non-distributable (foreign) layers
      --insecure                           Allow image references to be fetched without TLS
      --platform platform                  Specifies the platform in the form os/arch[/variant][:osversion] (e.g. linux/amd64). (default all)
  -v, --verbose                            Enable debug logs

$ regctl index create --help
Create a manifest list or OCI Index.

Usage:
  regctl index create <image_ref> [flags]

Aliases:
  create, init, new

Flags:
      --annotation stringArray        Annotation to set on manifest
      --artifact-type string          Include an artifactType value
      --by-digest                     Push manifest by digest instead of tag
      --desc-annotation stringArray   Annotation to add to descriptors of new entries
      --desc-platform string          Platform to set in descriptors of new entries
      --digest stringArray            Digest to include in new index
      --digest-tags                   Include digest tags
      --format string                 Format output with go template syntax
  -h, --help                          help for create
  -m, --media-type string             Media-type for manifest list or OCI Index (default "application/vnd.oci.image.index.v1+json")
      --platform stringArray          Platforms to include from ref
      --ref stringArray               References to include in new index
      --referrers                     Include referrers
      --subject string                Specify a subject tag or digest (this manifest must already exist in the repo)

例如使用

regctl
,看起来像:

$ regctl index create \
  --ref registry.example.org/someimage:1.0-amd64 \
  --ref registry.example.org/someimage:1.0-arm64 \
  registry.example.org/someimage:1.0
© www.soinside.com 2019 - 2024. All rights reserved.