---
title: Google Container Registry lifecycle policy for images retention
description: Is your Google Container Registry filling up, taking up storage and becoming expensive? How to handle imagesretention as a service?
---

[Revolgy blog ](https://www.revolgy.com/insights/blog)

# [Google Container Registry lifecycle policy for images retention](https://www.revolgy.com/insights/blog/google-container-registry-lifecycle-policy-for-images-retention)

 Written by [Marek Bartík](https://www.revolgy.com/insights/blog/author/marek-bartik) | October 14, 2019

Is your Google Container Registry filling up, taking up storage and becoming expensive? How to handle images retention as a service?

Amazon’s Elastic Container Registry has a feature called [Lifecycle Policies](https://docs.aws.amazon.com/AmazonECR/latest/userguide/LifecyclePolicies.html) to handle images retention. Google doesn’t have this feature. There is a [feature request in their tracker](https://issuetracker.google.com/issues/113559510) since Aug 2018 and there is not ETA for it so far…

There is a popular [bash script from Ahmet](https://gist.github.com/ahmetb/7ce6d741bd5baa194a3fac6b1fec8bb7) and [Go in CloudRun from Seth](https://github.com/sethvargo/gcr-cleaner) but none of them solve the requirements I needed. What exactly do I need?

I wanna scan my whole GCR and delete the digests that are:

- older than X days
- not being used in my kubernetes cluster
- not the most recent Y digests (I wanna keep, say, 20 most recent tagged digests)

When I check these requirements, I want to apply these lifecycle policies to all the images.

Say I have few images in GCR with certain prefixes:

```
eu.gcr.io/my-project/foo/bar/my-service:123
```

*eu.gcr.io* is the docker registry endpoint  
*my-project* is ID of my GCP project  
*foo/bar* is the prefix (“repo”)  
*my-service* is an image name  
*123* is a tag

*my-service:123* is an image with a tag, but wait, [what is the digest](https://windsock.io/explaining-docker-image-ids/)?

 Image vs Layers, taken from [https://windsock.io/explaining-docker-image-ids/](https://windsock.io/explaining-docker-image-ids/)

A docker image digest is an ID (hashing algorithm used and the hash computed). The digest can look like this:

*@sha256:296e2378f7a14695b2f53101a3bd443f656f823c46d13bf6406b91e9e9950ef0*

You can tag a digest with several tags, even zero tags = untagged image.

Let’s say build an image *my-service* and push it to docker registry. When pushing, I tag it with *:123. *The new produced digest has two tags,* :123 *and* :latest.*The digest that was tagged *:latest* before I pushed this image, got the *:latest* tag removed.

If I remove a tag from an image in GCR, I simply remove a tag from the digest, I don’t delete the digest though.

What I can delete, in order to save some space, is the digest, like this:

```
gcloud container images delete -q — force-delete-tags eu.gcr.io/my-project/foo/bar/my-service@sha256:296e2378f7a14695b2f53101a3bd443f656f823c46d13bf6406b91e9e9950ef0
```

Then, what do I need to do?

- Recursively scan *gcr.io *for all image prefixes (eu.gcr.io/my-project/foo/bar/my-service)
- For each prefix — list all its digests, delete the ones that don’t match my rules

How to check if they match the rules:

- sort them, preserve the most recent Y digests
- fetch pods and replicaSets’ image:tags (all of them, even the ones scaled to zero, we’d need these images in case of a rollback) from the k8s cluster, then go through the digests (that belong to that image name) and check if ANY of their tags contain a tag that is used in the cluster, preserve those
- check the rest of the digests, if they are older than X days, delete them

you could use standard kubectl to fetch the data:

```
kubectl get rs,po --all-namespaces -o jsonpath={..image} | tr ' ' '\n'
```

the gcr.io is exposing a docker v2 API, you can use a standard docker client or just curl using the gcloud token

```
ACCESS_TOKEN=$(gcloud auth print-access-token)curl --silent --show-error -u_token:"$ACCESS_TOKEN" -X GET "https://eu.gcr.io/v2/_catalog"
```

I implemented all of this using *bash/jq *(yep, that wasn’t a smart idea) and published it to github:

[https://github.com/marekaf/gcr-lifecycle-policy?source=post_page-----e0bc6bb88246----------------------](https://github.com/marekaf/gcr-lifecycle-policy?source=post_page-----e0bc6bb88246----------------------)

 

Right now I’m running this in Gitlab-CI pipeline on a cron schedule (once a day) to evaluate it’s dry-run logs for production GCP projects.

I’m planning on rewriting this to python (py-kubeng and docker-py) if Google will not to come up with ETA for this feature :(

 

## FAQs

Q1: What is a container?

A container is a logical “package” that contains everything an application needs in order to function, including the application itself, its dependencies, libraries, and configuration files.

Q2: How did containers evolve, and how are they different from virtual machines (VMs)?

Containers are an evolution from physical servers and then virtual machines. Unlike VMs, which virtualize entire machines including the operating system, containers only virtualize the application. Because they do not contain an OS image, containers are much smaller, more portable, and more flexible than VMs.

Q3: What is the primary advantage of containers being independent of their environment?

The primary advantage is that a container with your application can be run seamlessly in any environment — whether it’s AWS, GCP, Azure, a private data center, or a developer’s laptop. This allows developers to focus on application development without having to worry about where or how their applications will run.

Q4: How do containers lead to more efficient resource utilization?

Containers are small compared to conventional virtual machines and require fewer resources like memory or CPU. As a result, you can use your physical server resources more efficiently by stacking multiple containers on one server in a smart way, making the most out of the available hardware.

Q5: In what ways do containers improve the agility and stability of development and operations?

Because they are lightweight, containers can be started, stopped, replicated (horizontally scaled), or patched very quickly. This allows development and operations teams to be more independent, spend less time on debugging, and achieve faster development cycles, a quicker time-to-market, and a more stable infrastructure that can respond immediately to frequent changes like new releases or traffic spikes.

Q6: Why are containers considered an ideal solution for a hybrid infrastructure?

Since containers can be run anywhere, they are perfectly suited for hybrid infrastructure setups where applications run partially in a private data center and partially on a public cloud. Currently, there is no better solution for designing a hybrid infrastructure than to “containerize” your applications.

[View full post](https://www.revolgy.com/insights/blog/google-container-registry-lifecycle-policy-for-images-retention)

```json
{
  "@context" : "http://schema.org",
  "@type" : "BlogPosting",
  "author" : {
    "@type" : "Person",
    "name" : "Marek Bartík"
  },
  "dateModified" : "2025-09-22T15:06:43.410Z",
  "datePublished" : "2019-10-14T11:00:10Z",
  "headline" : "Google Container Registry lifecycle policy for images retention",
  "image" : {
    "@type" : "ImageObject",
    "height" : 698,
    "url" : "https://cdn2.hubspot.net/hubfs/4239923/unsplash.jpeg",
    "width" : 1060
  },
  "mainEntityOfPage" : "https://www.revolgy.com/insights/blog/google-container-registry-lifecycle-policy-for-images-retention",
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject",
      "height" : 60,
      "url" : "/hs/hsstatic/content_shared_assets/static-1.4092/img/default-amp-logo.png",
      "width" : 60
    },
    "name" : "Revolgy blog"
  }
}
```