Untagging images from AWS ECR (without deleting be like

I had to go full Rube Goldberg to clean up old image tags from closed PRs, while still leaving deletion of untagged image to the ECR repo’s own lifecycle policy. Never go full Rube Goldberg:


<span style="color:#63a35c;">name</span><span style="color:#323232;">: </span><span style="color:#183691;">ECR Retention Policy
</span><span style="color:#323232;">
</span><span style="color:#0086b3;">on</span><span style="color:#323232;">:
</span><span style="color:#323232;">  </span><span style="color:#63a35c;">pull_request</span><span style="color:#323232;">:
</span><span style="color:#323232;">    </span><span style="color:#63a35c;">types</span><span style="color:#323232;">:
</span><span style="color:#323232;">      - </span><span style="color:#183691;">closed
</span><span style="color:#323232;">  </span><span style="color:#63a35c;">workflow_call</span><span style="color:#323232;">:
</span><span style="color:#323232;">  </span><span style="color:#63a35c;">workflow_dispatch</span><span style="color:#323232;">:
</span><span style="color:#323232;">
</span><span style="color:#63a35c;">jobs</span><span style="color:#323232;">:
</span><span style="color:#323232;">  </span><span style="color:#63a35c;">clean-unused-ecr</span><span style="color:#323232;">:
</span><span style="color:#323232;">    </span><span style="color:#63a35c;">name</span><span style="color:#323232;">: </span><span style="color:#183691;">Delete unused container images
</span><span style="color:#323232;">    </span><span style="color:#63a35c;">runs-on</span><span style="color:#323232;">: </span><span style="color:#183691;">runs-on,runner=2cpu-linux-x64,run-id=${{ github.run_id }},image=ecr_login_image
</span><span style="color:#323232;">    </span><span style="color:#63a35c;">steps</span><span style="color:#323232;">:
</span><span style="color:#323232;">      - </span><span style="color:#63a35c;">name</span><span style="color:#323232;">: </span><span style="color:#183691;">Configure AWS credentials
</span><span style="color:#323232;">        </span><span style="color:#63a35c;">uses</span><span style="color:#323232;">: </span><span style="color:#183691;">aws-actions/configure-aws-credentials@v4
</span><span style="color:#323232;">        </span><span style="color:#63a35c;">with</span><span style="color:#323232;">:
</span><span style="color:#323232;">          </span><span style="color:#63a35c;">aws-region</span><span style="color:#323232;">: </span><span style="color:#183691;">${{ env.RUNS_ON_AWS_REGION }}
</span><span style="color:#323232;">      - </span><span style="color:#63a35c;">name</span><span style="color:#323232;">: </span><span style="color:#183691;">AWS ECR Login
</span><span style="color:#323232;">        </span><span style="color:#63a35c;">id</span><span style="color:#323232;">: </span><span style="color:#183691;">login-ecr
</span><span style="color:#323232;">        </span><span style="color:#63a35c;">uses</span><span style="color:#323232;">: </span><span style="color:#183691;">aws-actions/amazon-ecr-login@v2
</span><span style="color:#323232;">      - </span><span style="color:#63a35c;">name</span><span style="color:#323232;">: </span><span style="color:#183691;">AWS ECR Info
</span><span style="color:#323232;">        </span><span style="color:#63a35c;">shell</span><span style="color:#323232;">: </span><span style="color:#183691;">bash
</span><span style="color:#323232;">        </span><span style="color:#63a35c;">run</span><span style="color:#323232;">: </span><span style="font-weight:bold;color:#a71d5d;">|
</span><span style="color:#183691;">          echo "ECR_REGISTRY=${{ steps.login-ecr.outputs.registry }}" >> $GITHUB_ENV
</span><span style="color:#183691;">          echo "ECR_REPO=$(basename ${{ github.repository }})" >> $GITHUB_ENV
</span><span style="color:#323232;">      - </span><span style="color:#63a35c;">name</span><span style="color:#323232;">: </span><span style="color:#183691;">Docker meta
</span><span style="color:#323232;">        </span><span style="color:#63a35c;">id</span><span style="color:#323232;">: </span><span style="color:#183691;">docker_meta
</span><span style="color:#323232;">        </span><span style="color:#63a35c;">uses</span><span style="color:#323232;">: </span><span style="color:#183691;">docker/metadata-action@v5
</span><span style="color:#323232;">        </span><span style="color:#63a35c;">with</span><span style="color:#323232;">:
</span><span style="color:#323232;">          </span><span style="color:#63a35c;">images</span><span style="color:#323232;">: </span><span style="color:#183691;">${{ env.ECR_REGISTRY }}/${{ env.ECR_REPO }}
</span><span style="color:#323232;">          </span><span style="color:#63a35c;">flavor</span><span style="color:#323232;">: </span><span style="color:#183691;">suffix=-
</span><span style="color:#323232;">          </span><span style="color:#63a35c;">tags</span><span style="color:#323232;">: </span><span style="color:#183691;">type=raw,value=${{ github.head_ref || github.ref_name }}
</span><span style="color:#323232;">      </span><span style="font-style:italic;color:#969896;"># NOTE: This is convoluted because AWS ECR has no simple way to untag image without deletion
</span><span style="color:#323232;">      </span><span style="font-style:italic;color:#969896;"># given we want to leave deletion of untagged image to the ECR repo's own lifecycle policy
</span><span style="color:#323232;">      </span><span style="font-style:italic;color:#969896;"># https://stackoverflow.com/questions/70065254/remove-ecr-image-tag-despite-imagereferencedbymanifestlist-error
</span><span style="color:#323232;">      </span><span style="font-style:italic;color:#969896;"># https://github.com/aws/containers-roadmap/issues/1567
</span><span style="color:#323232;">      - </span><span style="color:#63a35c;">name</span><span style="color:#323232;">: </span><span style="color:#183691;">AWS ECR Cleanup
</span><span style="color:#323232;">        </span><span style="color:#63a35c;">shell</span><span style="color:#323232;">: </span><span style="color:#183691;">bash
</span><span style="color:#323232;">        </span><span style="color:#63a35c;">run</span><span style="color:#323232;">: </span><span style="font-weight:bold;color:#a71d5d;">|
</span><span style="color:#183691;">          REPO_EXISTS=$(aws ecr describe-repositories --repository-names $ECR_REPO 2>&1 || true)
</span><span style="color:#183691;">          if echo "${REPO_EXISTS}" | grep -q 'RepositoryNotFoundException'; then
</span><span style="color:#183691;">            echo "Repository not found, skipping cleanup."
</span><span style="color:#183691;">            exit 0
</span><span style="color:#183691;">          fi
</span><span style="color:#183691;">          IMAGE_TAGS=$(aws ecr list-images --repository-name $ECR_REPO --query 'imageIds[*].imageTag' --output text)
</span><span style="color:#183691;">
</span><span style="color:#183691;">          docker pull busybox
</span><span style="color:#183691;">          docker tag busybox $ECR_REGISTRY/$ECR_REPO:_
</span><span style="color:#183691;">          docker push $ECR_REGISTRY/$ECR_REPO:_
</span><span style="color:#183691;">
</span><span style="color:#183691;">          TEMP_IMAGE=$(
</span><span style="color:#183691;">            aws ecr batch-get-image 
</span><span style="color:#183691;">                --repository-name $ECR_REPO 
</span><span style="color:#183691;">                --image-ids imageTag=_ )
</span><span style="color:#183691;">          TEMP_MANIFEST=$(echo $TEMP_IMAGE | jq -r '.images[].imageManifest')
</span><span style="color:#183691;">          TEMP_DIGEST=$(echo $TEMP_IMAGE | jq -r '.images[].imageId.imageDigest')
</span><span style="color:#183691;">
</span><span style="color:#183691;">          TAG_PREFIX=$(echo ${{ fromJSON(steps.docker_meta.outputs.json).tags[0] }} | cut -d: -f2)
</span><span style="color:#183691;">          for TAG in $IMAGE_TAGS
</span><span style="color:#183691;">          do
</span><span style="color:#183691;">            if [[ $TAG == $TAG_PREFIX* ]]; then
</span><span style="color:#183691;">              docker tag busybox $ECR_REGISTRY/$ECR_REPO:$TAG
</span><span style="color:#183691;">              docker push $ECR_REGISTRY/$ECR_REPO:$TAG
</span><span style="color:#183691;">              echo "Untaged image $TAG"
</span><span style="color:#183691;">            fi
</span><span style="color:#183691;">          done
</span><span style="color:#183691;">
</span><span style="color:#183691;">          # Delete the temporary image by digest
</span><span style="color:#183691;">          aws ecr batch-delete-image 
</span><span style="color:#183691;">            --repository-name $ECR_REPO 
</span><span style="color:#183691;">            --image-ids imageDigest=$TEMP_DIGEST
</span>
PlexSheep,

What is untag?

ruffsl,
@ruffsl@programming.dev avatar

Tagging an image is simply associating a string value to an image pushed to a container registry, as a human readable identifier. Unlike an image ID or image digest sha, an image tag is only loosely associated, and can be remapped later to another image in the same registry repo, e.g latest. Untagging is simply removing the tag from the registry, but not necessarily the associated image itself.

tatterdemalion,
@tatterdemalion@programming.dev avatar

AWS CLI is trash compared to gcloud in general.

deegeese,

The Wal-Mart of cloud providers.

  • All
  • Subscribed
  • Moderated
  • Favorites
  • programmer_humor@programming.dev
  • DreamBathrooms
  • magazineikmin
  • cubers
  • everett
  • rosin
  • Youngstown
  • ngwrru68w68
  • slotface
  • osvaldo12
  • Durango
  • kavyap
  • InstantRegret
  • tacticalgear
  • khanakhh
  • megavids
  • GTA5RPClips
  • normalnudes
  • thenastyranch
  • mdbf
  • ethstaker
  • modclub
  • Leos
  • tester
  • provamag3
  • cisconetworking
  • anitta
  • JUstTest
  • lostlight
  • All magazines