Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Script to clean up Google Container Registry images pushed before a particular date
#!/bin/bash
# Copyright © 2017 Google Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
IFS=$'\n\t'
set -eou pipefail
if [[ "$#" -ne 2 || "${1}" == '-h' || "${1}" == '--help' ]]; then
cat >&2 <<"EOF"
gcrgc.sh cleans up tagged or untagged images pushed before specified date
for a given repository (an image name without a tag/digest).
USAGE:
gcrgc.sh REPOSITORY DATE
EXAMPLE
gcrgc.sh gcr.io/ahmet/my-app 2017-04-01
would clean up everything under the gcr.io/ahmet/my-app repository
pushed before 2017-04-01.
EOF
exit 1
elif [[ "${#2}" -ne 10 ]]; then
echo "wrong DATE format; use YYYY-MM-DD." >&2
exit 1
fi
main(){
local C=0
IMAGE="${1}"
DATE="${2}"
for digest in $(gcloud container images list-tags ${IMAGE} --limit=999999 --sort-by=TIMESTAMP \
--filter="timestamp.datetime < '${DATE}'" --format='get(digest)'); do
(
set -x
gcloud container images delete -q --force-delete-tags "${IMAGE}@${digest}"
)
let C=C+1
done
echo "Deleted ${C} images in ${IMAGE}." >&2
}
main "${1}" "${2}"
@wibobm

This comment has been minimized.

Copy link

wibobm commented Mar 28, 2018

Pretty sweet script. Could I bother you to make a version that does this but KEEPs tagged versions?

@falkvoigt

This comment has been minimized.

Copy link

falkvoigt commented Apr 9, 2018

i have a littel upgrade for LTS Images where you need to keep older stuff

COUNTALL="$(gcloud container images list-tags ${IMAGE} --limit=999999 --sort-by=TIMESTAMP  | grep -v DIGEST | wc -l)"
  for digest in $(gcloud container images list-tags ${IMAGE} --limit=999999 --sort-by=TIMESTAMP \
    --filter="timestamp.datetime < '${DATE}'" --format='get(digest)'); do

    if [ $(( $COUNTALL - $C )) -ge 10 ]
    then
      (
        set -x
        gcloud container images delete -q --force-delete-tags "${IMAGE}@${digest}"
      )
      let C=C+1
    else
      echo "Deleted $(( $C - 1 )) images in ${IMAGE}." >&2
      break
    fi   
  done

you could define how many Images should stay

@evaldasou

This comment has been minimized.

Copy link

evaldasou commented May 17, 2018

@falkvoigt can You update Your script? now it's incorrectly formated in gist, - it does nothing if You just run it! :)

@ahmetb

This comment has been minimized.

Copy link
Owner Author

ahmetb commented May 25, 2018

@wibobm you can pin to a commit number on gists easily.
@falkvoigt what does your change do? mind explaining?
@evaldasou I just edited his comment to correct formatting

@jabaganz

This comment has been minimized.

Copy link

jabaganz commented Jun 8, 2018

@wibobm i ran into the same requirement. Its easy to accomplish by changing the filter in line 44 of the orinial script to:

--filter "NOT tags:* AND timestamp.datetime < '${DATE}'"

@or-shachar

This comment has been minimized.

Copy link

or-shachar commented Dec 3, 2019

I think there's a way to delete multiple images in the same command, which can be a time saver

@ahmetb

This comment has been minimized.

Copy link
Owner Author

ahmetb commented Dec 4, 2019

UPDATE:

Consider using https://github.com/sethvargo/gcr-cleaner which is a Cloud Run app that you deploy and can be triggered periodically with Cloud Scheduler to garbage collect old images.

@jeunii

This comment has been minimized.

Copy link

jeunii commented Jan 6, 2020

Quick question. I have something similar that Im going to implement. But I want this script to run inside a Pod in my k8s cluster.

So after dockerizing this script and invoking this as a cronjob in my cluster, how can I make sure that im authorized run the gcloud list and delete image commands ?

@arsenhovhannisyan95

This comment has been minimized.

Copy link

arsenhovhannisyan95 commented Jun 30, 2020

By default, K8S ReplicaSet keeps 10 versions revision history this script keeps that versions and delete all other from GCR, you can change it in Deployment "revisionHistoryLimit: 10" .

You need to have service account with following permissions
Kubernetes Engine Cluster Viewer
Kubernetes Engine Developer
Kubernetes Engine Service Agent
Storage Object Admin

##!/bin/bash
set -eou pipefail
echo G-Cloud Authentication
gcloud auth activate-service-account ${CLIENT_EMAIL} --key-file=serviceaccount.json --project=${PROJECT_ID}
echo Get Kubernetes Config
gcloud container clusters get-credentials ${PROJECT_ID} --zone ${ZONE} --project ${PROJECT_ID}
gcloud container images list-tags ${IMAGE} --limit=unlimited --sort-by=TIMESTAMP | tr ' ' '|' | cut -d'|' -f3 | sed '/^[[:space:]]*$/d' > repo-images.txt
kubectl get rs --all-namespaces -o jsonpath={..image} | tr ' ' '\n' | grep -i ${IMAGE} | sort -u | cut -d':' -f2 > used-images.txt

main(){
local C=0
for tag in $(grep -vxFf used-images.txt repo-images.txt); do
(
set -x
gcloud container images delete -q --force-delete-tags "${IMAGE}:${tag}"
)
let C=C+1
done
echo "Deleted ${C} images in ${IMAGE}." >&2
}

main

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.