Search code examples
amazon-web-servicesdockeramazon-ecr

How to delete untagged images from AWS ECR Container Registry


When pushing images to Amazon ECR, if the tag already exists within the repo the old image remains within the registry but goes in an untagged state.

So if i docker push image/haha:1.0.0 the second time i do this (provided that something changes) the first image gets untagged from AWS ECR.

Is there a way to safely clean up all the registries from untagged images?


Solution

  • I actually forged a one line solution using 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
    

    What it's doing is:

    • get all repositories
    • for each repository give me all images with tagStatus=UNTAGGED
    • for each image+repo issue a batch-delete-image

    If you have JQ, you can use this version that is more robust by not relying on the changing text format and also more efficient as it batch deletes once per repository:

    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
    

    This has been broken up into more lines for readability, so better put it into a function in your .bashrc, but you could of course stuff it into a single line:

    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