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

Ben*_*eer 12 amazon-web-services docker amazon-ecr docker-buildkit

我开始使用 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  . 
Run Code Online (Sandbox Code Playgroud)

检查图像:

 docker buildx imagetools inspect 1234567890.dkr.ecr.eu-west-1.amazonaws.com/my-service/my-image:1.0
Run Code Online (Sandbox Code Playgroud)

显示:

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
Run Code Online (Sandbox Code Playgroud)

然而,ECR 将 2 个子图像显示为untagged

小智 11

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

完成初始操作后:

docker buildx build --platform "linux/amd64,linux/arm64" --tag 1234567890.dkr.ecr.eu-west-1.amazonaws.com/my-service/my-image:1.0 --push  . 
Run Code Online (Sandbox Code Playgroud)

我跟进:

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  .
Run Code Online (Sandbox Code Playgroud)

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

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


BMi*_*tch 6

There are several ways to tag the image, but they all involve pushing the platform specific manifest with the desired tag. With docker, you can pull the image, retag it, and push it, but the downside is you'll have to pull every layer.

A much faster option is to only transfer the manifest json with registry API calls. You could do this with curl, but auth becomes complicated. There are several tools for working directly with registries, including Googles crane, RedHat's skopeo, and my own regclient. Regclient includes the regctl command which would implement this like:

image=1234567890.dkr.ecr.eu-west-1.amazonaws.com/my-service/my-image
tag=1.0
regctl image copy \
  ${image}@$(regctl image digest --platform linux/amd64 $image:$tag) \
  ${image}:${tag}-linux-amd64
regctl image copy \
  ${image}@$(regctl image digest --platform linux/arm64 $image:$tag) \
  ${image}:${tag}-linux-arm64
Run Code Online (Sandbox Code Playgroud)

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

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