在 ECR 中标记多平台图像会创建未标记的清单

Tagging multi-platform images in ECR creates untagged manifests

我已经开始使用 docker buildx 来标记多平台映像并将其推送到 ECR。然而,ECR 似乎将标签应用于父清单,并将每个相关清单保留为未标记。 ECR 似乎确实可以防止删除子清单,但它会使管理孤立的未标记图像的清理变得复杂。

有没有办法以某种方式标记这些子清单?

例如,考虑这个推送:

docker buildx build --platform "linux/amd64,linux/arm64" --tag 1234567890.dkr.ecr.eu-west-1.amazonaws.com/my-service/my-image:1.0 --push  . 

检查图像:

 docker buildx imagetools inspect 1234567890.dkr.ecr.eu-west-1.amazonaws.com/my-service/my-image:1.0

显示:

Name:      1234567890.dkr.ecr.eu-west-1.amazonaws.com/my-service/my-image:1.0
MediaType: application/vnd.docker.distribution.manifest.list.v2+json
Digest:    sha256:4221ad469d6a18abda617a0041fd7c87234ebb1a9f4ee952232a1287de73e12e
       
Manifests: 
    Name:      1234567890.dkr.ecr.eu-west-1.amazonaws.com/my-service/my-image:1.0@sha256:c1b0c04c84b025357052eb513427c8b22606445cbd2840d904613b56fa8283f3
    MediaType: application/vnd.docker.distribution.manifest.v2+json
    Platform:  linux/amd64
         
    Name:      1234567890.dkr.ecr.eu-west-1.amazonaws.com/my-service/my-image:1.0@sha256:828414cad2266836d9025e9a6af58d6bf3e6212e2095993070977909ee8aee4b
    MediaType: application/vnd.docker.distribution.manifest.v2+json
    Platform:  linux/arm64

但是,ECR 将 2 个子图像显示为 untagged

有多种标记图像的方法,但它们都涉及使用所需标记推送特定于平台的清单。使用 docker,您可以拉取图像、重新标记并推送它,但缺点是您必须拉取每一层。

一个更快的选择是仅通过注册表 API 调用传输清单 json。你可以用 curl 做到这一点,但 auth 变得复杂。有多种工具可以直接与注册管理机构合作,包括 Google 的 crane、RedHat 的 skopeo 和我自己的 regclient。 Regclient 包含 regctl 命令,它可以像这样实现:

regctl image copy \
  1234567890.dkr.ecr.eu-west-1.amazonaws.com/my-service/my-image:1.0@sha256:c1b0c04c84b025357052eb513427c8b22606445cbd2840d904613b56fa8283f3 \
  1234567890.dkr.ecr.eu-west-1.amazonaws.com/my-service/my-image:1.0-linux-amd64

regctl image copy \
  1234567890.dkr.ecr.eu-west-1.amazonaws.com/my-service/my-image:1.0@sha256:828414cad2266836d9025e9a6af58d6bf3e6212e2095993070977909ee8aee4b \
  1234567890.dkr.ecr.eu-west-1.amazonaws.com/my-service/my-image:1.0-linux-arm64

您还可以编写一个自动修复此问题的脚本,列出注册表中的所有标签,提取尚未具有该平台的标签的清单列表,并 运行 将图像副本重新标记每个平台的清单。但是,在 buildx 推送图像后编写 buildx 作业脚本以包含诸如 regctl 之类的内容可能会更容易和更快。

请注意,如果您使用 cred 帮助程序登录 ECR,则 regctl 可以将其与本地命令一起使用。如果想 运行 将 regctl 作为容器,并且您专门使用 ecr-login,请使用图像的 alpine 版本,因为它们包含辅助二进制文件。

除了 Brandon 在上面提到的使用 regctl 之外,如果您希望将它与 ECR 凭据助手一起使用,这里是 skopeo 的命令。 https://github.com/awslabs/amazon-ecr-credential-helper

skopeo copy \ 
docker://1234567890.dkr.ecr.us-west-2.amazonaws.com/Whosebug@sha256:1badbc699ed4a1785295baa110a125b0cdee8d854312fe462d996452b41e7755 \
docker://1234567890.dkr.ecr.us-west-2.amazonaws.com/Whosebug:1.0-linux-arm64

https://github.com/containers/skopeo

  • Paavan Mistry,AWS 容器DA

我 运行 遇到了同样的问题。到目前为止,我的解决方案似乎比其他一些建议更容易一些,但我仍然不喜欢它。

完成初始后:

docker buildx build --platform "linux/amd64,linux/arm64" --tag 1234567890.dkr.ecr.eu-west-1.amazonaws.com/my-service/my-image:1.0 --push  . 

我跟进:

docker buildx build --platform "linux/amd64" --tag 1234567890.dkr.ecr.eu-west-1.amazonaws.com/my-service/my-image:1.0-amd --push  .
docker buildx build --platform "linux/arm64" --tag 1234567890.dkr.ecr.eu-west-1.amazonaws.com/my-service/my-image:1.0-arm --push  .

这让我获得了同时构建多个平台的并行构建速度,并让我获得了在 ECR 中标记的图像。由于缓存了构建信息,它非常快,它似乎只是推送标签,仅此而已。在测试中,我刚刚执行的第一个命令的 buildx 时间为 0.5 秒。第二个用了0.7秒

也就是说,我对这个解决方案并不满意,并且在寻找更好的解决方案时发现了这个问题。