【问题标题】:How to delete untagged images from AWS ECR Container Registry如何从 AWS ECR Container Registry 中删除未标记的图像
【发布时间】:2017-04-18 09:00:52
【问题描述】:

将图像推送到 Amazon ECR 时,如果存储库中已存在标签,则旧图像仍保留在注册表中,但处于未标记状态。

因此,如果我第二次 docker push image/haha:1.0.0 执行此操作(前提是发生了变化),则第一个图像会从 AWS ECR 中取消标记。

有没有办法从未标记的图像中安全地清除所有注册表?

【问题讨论】:

    标签: amazon-web-services docker amazon-ecr


    【解决方案1】:

    我实际上使用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 的图像
    • 对于每个图像+repo 发出一个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
    

    为了便于阅读,它被分成了更多行,所以put it into a function in your .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
    

    【讨论】:

    • 可能是 AWS CLI 输出已更改,但 awk '{print $5}' 提供了 ARN。获取存储库名称应该是awk '{print $6}'
    • 原始答案不再有效,因为输出不匹配。我会更新的。
    【解决方案2】:

    您可以在一个请求中删除所有图像,无需循环:

    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 以避免在没有未标记的图像时出现错误代码。

    【讨论】:

    • 我没有'--filter'选项,你用的是什么版本? (我有 aws-cli/1.10.39)
    • 更新:v1.11.44 支持过滤器
    • ECR 不支持超过 100 个图像。这修复了:``` IMAGES_TO_DELETE=$( aws ecr list-images --region $ECR_REGION --repository-name $ECR_REPO --filter "tagStatus=UNTAGGED" --query 'imageIds[*]' --max-items 100 --output json ) aws ecr batch-delete-image --region $ECR_REGION --repository-name $ECR_REPO --image-ids "$IMAGES_TO_DELETE" ||真正的```
    【解决方案3】:

    现在,ECR 支持生命周期策略 (https://docs.aws.amazon.com/AmazonECR/latest/userguide/LifecyclePolicies.html),您可以使用它自动删除未标记的图像。

    使用控制台设置生命周期策略预览

    https://console.aws.amazon.com/ecs/ 打开 Amazon ECS 控制台。

    从导航栏中,选择包含 执行生命周期策略预览的存储库。

    在导航窗格中,选择存储库并选择一个存储库。

    在所有存储库:repository_name 页面上,选择 Dry-Run 生命周期规则,添加。

    为您的生命周期策略规则输入以下详细信息:

    对于规则优先级,键入规则优先级的数字。

    对于规则描述,键入生命周期策略的描述 规则。

    对于图像状态,选择已标记或未标记。

    如果您为图像状态指定了标记,那么为标记前缀列表指定, 您可以选择指定要拍摄的图像标签列表 根据您的生命周期策略采取行动。如果您指定了未标记,则此 字段必须为空。

    对于匹配条件,选择计数类型、计数值和 计数单位(如果适用)。

    选择保存

    通过重复步骤 5-7 创建其他生命周期策略规则。

    要运行生命周期策略预览,请选择保存并预览结果。

    在预览图像结果下,查看您的生命周期的影响 政策预览。

    如果您对预览结果感到满意,请选择 Apply as 生命周期策略以创建具有指定的生命周期策略 规则。

    从这里: https://docs.aws.amazon.com/AmazonECR/latest/userguide/lpp_creation.html

    【讨论】:

    • 我尝试了您的答案中列出的步骤,但它似乎没有删除旧图像。在试运行策略时,它会正确列出我打算删除的所有图像,但在应用策略时它们实际上并没有被删除。我有什么遗漏吗?
    • @Broadwell ...它在应用策略后不会立即运行。给它一些时间(一小时到两小时),你会发现它运行起来了。
    【解决方案4】:

    设置生命周期政策绝对是最好的管理方式。话虽如此 - 如果您确实有一堆要删除的图像,请记住批量删除图像的最大值为 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
    

    【讨论】:

      【解决方案5】:

      基于@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)
      

      【讨论】:

        【解决方案6】:

        如果您想从存储库中删除未标记的图像,您可以简单地创建 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"
                }
            }
          ]
        }
        

        【讨论】:

          猜你喜欢
          • 2020-05-09
          • 1970-01-01
          • 2020-10-30
          • 2015-10-10
          • 1970-01-01
          • 2021-11-28
          • 1970-01-01
          • 1970-01-01
          • 2015-06-30
          相关资源
          最近更新 更多