我目前正在创建一个python脚本,以便使用AWS CLI创建AWS ECR的适配器。我有一个暂存环境,其中包含1.0.0版本的版本化测试容器。现在我尝试使用以下控制流重新标记它:
- 保存清单。
aws ecr batch-get-image --repository-name staging/test --image-ids imageTag=1.0.0 --output text
(aws cli的json输出有bug,无法进行健壮的解析) - 删除旧的"最新的";标签:
aws ecr batch-delete-image --repository-name staging/test --image-ids imageTag=latest
- 使用图像摘要和manifest json重新标记图像:
aws ecr put-image --repository-name staging/test --image-tag latest --image-manifest file://manifest.json --image-digest sha256:foobar
问题:ECR抛出一个描述图像摘要不相同的异常。但是没有"最新"的图片——它没有标记。因此,我尝试将图像标记为一个不存在的版本"2.0.0",并且有一次没有摘要。ECR标记图像并计算一个新的图像摘要——这似乎是核心问题。
联系AWS支持后,似乎一旦使用cli的纯文本输出,json就会发生变化。如果你使用"jq"提供的AWS解决方案,一切都很好。其他方法将改变空格,ECR将计算不同的摘要。
最后看起来很奇怪,清单的内容和周围的json语法一样重要。
所以,事实证明图像的图像摘要是其清单的sha256摘要。
这就解释了为什么manifest JSON文件中不同的空白会导致不同的摘要。
一个奇怪的结果是,虽然aws ecr batch-get-image --query 'images[0].imageManifest'
返回的清单正是您所需要的文档,但将其输送到文件将很容易添加最后一个换行符,从而修改清单摘要。
一个解决方案是用head -c -1
aws ecr batch-get-image --repository-name staging/test --image-ids imageTag=1.0.0 --output=text --query 'images[0].imageManifest' | head -c -1 > manifest.json
aws ecr put-image --repository-name staging/test --image-tag latest --image-manifest file://manifest.json --image-digest sha256:foobar
我修复了这个问题(在对以下python代码感到沮丧之后):
# read exact "manifest" of src_tag to be duplicated
_, img_data = run_cmd(
f"aws ecr batch-get-image --repository-name {repo_name} --image-ids imageTag={src_tag} --output json --region {AWS_CONF['region']} --profile {AWS_CONF['profile']}",
)
img_data = json.loads(img_data)
manifest_str = img_data["images"][0]["imageManifest"]
# retag image (using boto3 instead of CLI to ensure the exact manifest string is passed in)
import boto3
ecr_client = boto3.client("ecr", region_name=AWS_CONF["region"])
response = ecr_client.put_image(
registryId=registry_id,
repositoryName=repo_name,
imageManifest=manifest_str,
imageManifestMediaType="string",
imageTag=dest_tag,
)
if response["ResponseMetadata"]["HTTPStatusCode"] != 200:
print(f"ERROR: failed to retag image! (status code 200)")
注意run_cmd()
是一个自定义函数,它调用子进程并返回字符串输出。请注意,读取src_tag的清单几乎肯定可以用boto3 API来完成,但我选择不进一步重构我的代码。
对我来说,我无法让这与aws ecr batch-get-image
一起工作,因为清单字符串总是略有变化。此解决方案确保使用与src_tag完全相同的清单字符串(避免通过将其解析为json等间接修改它)。