When we push repeatedly into gcr.io
with the same image name and a version (tag), there is a high number of untagged images.
Is there a simple way to remove all untagged images for a single image using the gcloud
CLI tool to avoid incurring Storage costs?

- 876
- 12
- 27

- 4,176
- 2
- 26
- 38
7 Answers
gcloud container images list-tags gcr.io/project-id/repository --format=json --limit=unlimited
will give you an easily consumable json blob of info for images in a repo (such as digests w/ associated tags).
In order to just enumerate all digests which lack tags:
gcloud container images list-tags gcr.io/project-id/repository --filter='-tags:*' --format='get(digest)' --limit=unlimited
Which you can iterate over and delete with:
gcloud container images delete --quiet gcr.io/project-id/repository@DIGEST

- 595
- 4
- 8
Handy when you glue them together with awk and xargs
gcloud container images list-tags gcr.io/${PROJECT_ID}/${IMAGE} --filter='-tags:*' --format='get(digest)' --limit=unlimited | awk '{print "gcr.io/${PROJECT_ID}/${IMAGE}@" $1}' | xargs gcloud container images delete --quiet
The previous one-liner was not working for me. I am using this one at the moment:
- Deletes all the un-tagged images for a given PROJECT_ID and IMAGE
- Uses Xargs -I, which creates a token (called {arg} in this case)
gcloud container images list-tags gcr.io/${PROJECT_ID}/${IMAGE} \
--filter='-tags:*' --format='get(digest)' --limit=unlimited |\
xargs -I {arg} gcloud container images delete \
"gcr.io/${PROJECT_ID}/${IMAGE}@{arg}" --quiet

- 2,676
- 4
- 17
- 30

- 676
- 7
- 17
-
Thanks, the other answer wasn't working for me either on my bash shell because the ENV var wasn't interpolating within single quotes. – Ninjaxor Jan 22 '23 at 18:33
My use case was to delete all untagged images from a specific project. I wrote simple script to achieve this:
delete_untagged() {
echo " |-Deleting untagged images for $1"
while read digest; do
gcloud container images delete $1@$digest --quiet 2>&1 | sed 's/^/ /'
done < <(gcloud container images list-tags $1 --filter='-tags:*' --format='get(digest)' --limit=unlimited)
}
delete_for_each_repo() {
echo "|-Will delete all untagged images in $1"
while read repo; do
delete_untagged $repo
done < <(gcloud container images list --repository $1 --format="value(name)")
}
delete_for_each_repo gcr.io/<project-id>/<repository>
The full script can be found here: https://gist.github.com/lahsivjar/2b011d69368a26af7043d4aa70ec78f8
Hope it will be helpful to someone

- 29
- 5
It is documented here but one important thing to be noted is that
DIGEST must be of the form "
sha256:<digest>
"
So catch first the form sha256:<digest>
of untagged images
$ DIGEST=`gcloud container images list-tags gcr.io/[PROJECT-ID]/[IMAGE] \
--filter='-tags:*' --format='get(digest)'`
$ echo $DIGEST
sha256:7c077a9ca45aea7134d8436a3071aceb5fa62758cc86eadec63f02692b7875f7
Then use the variable to remove it
$ gcloud container images delete --quiet gcr.io/[PROJECT-ID]/[IMAGE]@$DIGEST
Digests:
- gcr.io/[PROJECT-ID]/[IMAGE]@sha256:7c077a9ca45a......
Deleted [gcr.io/[PROJECT-ID]/[IMAGE]@sha256:7c077a9ca45a......].

- 9,880
- 3
- 65
- 77
Powershell version of the one liner posted by @Benos
gcloud container images list-tags gcr.io/myprojectname/myimagename --filter='-tags:*' --format='get(tags)' --limit=unlimited | ForEach-Object { gcloud container images delete "gcr.io/myprojectname/myimagename:$PSItem" --quiet }
Remove the --filter='-tags:*'
to delete all tags of a certain image (this is what I was trying to accomplish)

- 2,774
- 4
- 36
- 52
-
Had to change : to @ to get it to work: gcr.io/myprojectname/myimagename@$PSItem – Emmanuel Osimosu Oct 11 '20 at 17:14
Corrected Powershell Command
gcloud container images list-tags gcr.io/myprojectname/myimagename --filter='-tags:*' --format='get(digest)' --limit=unlimited | ForEach-Object { gcloud container images delete "gcr.io/myprojectname/myimagename@$PSItem" --quiet }

- 25
- 5