将映像推送到 Amazon ECR 时,如果存储库中已存在标签,则旧映像仍保留在注册表中,但处于未标记状态。
因此,如果我第二次使用 docker pushimage/haha:1.0.0
执行此操作(前提是发生了变化),则第一个图像会从AWS ECR
.
有没有办法从未标记的图像中安全地清理所有注册表?
将映像推送到 Amazon ECR 时,如果存储库中已存在标签,则旧映像仍保留在注册表中,但处于未标记状态。
因此,如果我第二次使用 docker pushimage/haha:1.0.0
执行此操作(前提是发生了变化),则第一个图像会从AWS ECR
.
有没有办法从未标记的图像中安全地清理所有注册表?
您可以在一个请求中删除所有图像,而无需循环:
IMAGES_TO_DELETE=$( aws ecr list-images --region $ECR_REGION --repository-name $ECR_REPO --filter "tagStatus=UNTAGGED" --query 'imageIds[*]' --output json )
aws ecr batch-delete-image --region $ECR_REGION --repository-name $ECR_REPO --image-ids "$IMAGES_TO_DELETE" || true
首先,它以 json 格式获取未标记的图像列表:
[ {"imageDigest": "sha256:..."}, {"imageDigest": "sha256:..."}, ... ]
然后它将该列表发送到batch-image-delete
.
当没有未标记的图像时,需要最后一个|| true
以避免错误代码。
现在,ECR 支持生命周期策略 ( https://docs.aws.amazon.com/AmazonECR/latest/userguide/LifecyclePolicies.html ),您可以使用它自动删除未标记的图像。
使用控制台设置生命周期策略预览
在https://console.aws.amazon.com/ecs/打开 Amazon ECS 控制台。
从导航栏中,选择包含要在其上执行生命周期策略预览的存储库的区域。
在导航窗格中,选择存储库并选择存储库。
在所有存储库:repository_name 页面上,选择试运行生命周期规则、添加。
为您的生命周期策略规则输入以下详细信息:
对于规则优先级,键入规则优先级的数字。
对于规则描述,键入生命周期策略规则的描述。
对于图像状态,选择已标记或未标记。
如果您为图像状态指定了已标记,那么对于标记前缀列表,您可以选择指定一个图像标记列表,以对您的生命周期策略执行操作。如果您指定了未标记,则此字段必须为空。
对于匹配条件,为计数类型、计数和计数单位(如果适用)选择值。
选择保存
通过重复步骤 5–7 创建其他生命周期策略规则。
要运行生命周期策略预览,请选择保存并预览结果。
在预览图像结果下,查看您的生命周期策略预览的影响。
如果您对预览结果感到满意,请选择应用为生命周期策略以创建具有指定规则的生命周期策略。
从这里: https ://docs.aws.amazon.com/AmazonECR/latest/userguide/lpp_creation.html
我实际上使用了一个单线解决方案aws cli
aws ecr describe-repositories --output text | awk '{print $5}' | egrep -v '^$' | while read line; do repo=$(echo $line | sed -e "s/arn:aws:ecr.*\///g") ; aws ecr list-images --repository-name $repo --filter tagStatus=UNTAGGED --query 'imageIds[*]' --output text | while read imageId; do aws ecr batch-delete-image --repository-name $repo --image-ids imageDigest=$imageId; done; done
它正在做的是:
tagStatus=UNTAGGED
batch-delete-image
如果你有JQ,你可以使用这个版本,它不依赖于不断变化的文本格式,并且更高效,因为它在每个存储库中批量删除一次:
aws ecr describe-repositories \
| jq --raw-output .repositories[].repositoryName \
| while read repo; do
imageIds=$(aws ecr list-images --repository-name $repo --filter tagStatus=UNTAGGED --query 'imageIds[*]' --output json | jq -r '[.[].imageDigest] | map("imageDigest="+.) | join (" ")');
if [[ "$imageIds" == "" ]]; then continue; fi
aws ecr batch-delete-image --repository-name $repo --image-ids $imageIds;
done
为了便于阅读,这已被分成更多行,因此最好将其放入 .bashrc 中的函数中,但您当然可以将其填充到一行中:
aws ecr describe-repositories | jq --raw-output .repositories[].repositoryName | while read repo; do imageIds=$(aws ecr list-images --repository-name $repo --filter tagStatus=UNTAGGED --query 'imageIds[*]' --output json | jq -r '[.[].imageDigest] | map("imageDigest="+.) | join (" ")'); if [[ "$imageIds" == "" ]]; then continue; fi; aws ecr batch-delete-image --repository-name $repo --image-ids $imageIds; done
设置生命周期策略绝对是管理此问题的最佳方式。话虽如此 - 如果您确实有一堆要删除的图像,请记住批量删除图像的最大值为 100。所以您需要这样做是因为未标记图像的数量大于 100:
IMAGES_TO_DELETE=$( aws ecr list-images --repository-name $ECR_REPO --filter "tagStatus=UNTAGGED" --query 'imageIds[0:100]' --output json )
echo $IMAGES_TO_DELETE | jq length # Gets the number of results
aws ecr batch-delete-image --repository-name $ECR_REPO --image-ids "$IMAGES_TO_DELETE" --profile qa || true
如果要从存储库中删除未标记的图像,只需创建 JSON 生命周期策略,然后使用 python 将 JSON 策略应用于存储库
就我而言,我将该策略应用于 ECR 中的所有 ECR 存储库,并且我在当前目录中创建了一个“lifecyclepolicy.json”文件,其中添加了 ECR 的生命周期策略
这是我的python代码:-
import os
import json
import boto3
def ecr_lifecycle(lifecycle_policy):
ecr_client = boto3.client('ecr')
repositories = []
describe_repo_paginator = ecr_client.get_paginator('describe_repositories')
for response_list_repopaginator in describe_repo_paginator.paginate():
for repo in response_list_repopaginator['repositories']:
repositories.append(repo['repositoryName'])
for repository in repositories:
response=ecr_client.put_lifecycle_policy(repositoryName=repository,
lifecyclePolicyText=json.dumps(lifecycle_policy))
return response
if __name__ == '__main__':
path = os.path.dirname(__file__)
json_file = open(os.path.join(path, 'lifecyclepolicy.json'))
data = json.load(json_file)
ecr_lifecycle(data)
如果您想查看 JSON 文件:-
{
"rules": [
{
{
"rulePriority": 10,
"description": "Only keep untagged images for 7 days",
"selection": {
"tagStatus": "untagged",
"countType": "sinceImagePushed",
"countUnit": "days",
"countNumber": 7
}
"action": {
"type": "expire"
}
}
]
}
基于@Ken J 的回答,
这是一个可以清理所有 ECR 的 python 脚本:
#!/usr/bin/python3
import subprocess
import json
import os
# Based on: https://stackoverflow.com/questions/40949342/how-to-delete-untagged-images-from-aws-ecr-container-registry
region="us-east-1"
debug = False
def _runCommand(command):
if debug:
print(" ".join(command))
p = subprocess.Popen(command, shell = False, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
return [p.stdout.read().decode("utf-8"), p.stderr.read().decode("utf-8")]
command = "aws ecr describe-repositories --region " + region + " --output json".split(" ")
data = _runCommand(command)[0]
for i in json.loads(data)["repositories"]:
name = i["repositoryName"]
print(name)
command = ["aws", "ecr", "list-images", "--region", region, "--repository-name", name, "--filter", "tagStatus=UNTAGGED", "--query", 'imageIds[*]', "--output" , "json"]
data = _runCommand(command)[0]
command = ["aws", "ecr", "batch-delete-image", "--region", region, "--repository-name", name, "--image-ids",data]
data = _runCommand(command)[0]
print(data)