<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Moritz Rinow</title>
    <description>The latest articles on DEV Community by Moritz Rinow (@moritzrinow).</description>
    <link>https://dev.to/moritzrinow</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1472900%2F460db82f-6d23-4e5b-b47f-1f0931b2f77e.jpeg</url>
      <title>DEV Community: Moritz Rinow</title>
      <link>https://dev.to/moritzrinow</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/moritzrinow"/>
    <language>en</language>
    <item>
      <title>Automatic tag deletion for Docker registries</title>
      <dc:creator>Moritz Rinow</dc:creator>
      <pubDate>Tue, 13 May 2025 15:17:09 +0000</pubDate>
      <link>https://dev.to/moritzrinow/automatic-tag-deletion-for-docker-registries-122h</link>
      <guid>https://dev.to/moritzrinow/automatic-tag-deletion-for-docker-registries-122h</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Docker registries are essential nowadays in a world of containerized workloads. Want to run your app on Kubernetes? You need to push it to a registry first. If you don't want to pay for a managed, private registry service, you self-host your own.&lt;/p&gt;

&lt;p&gt;The biggest pain point of Docker registries is storage. If you choose to store registry data on a local disk, you are limited by capacity.&lt;br&gt;
If you choose to use cloud object-storage (Azure, S3, etc.), you are limited by costs.&lt;/p&gt;

&lt;p&gt;Over time, registries accumulate a lot of garbage in the form of blobs referenced by old images that are not needed anymore. Many registry implementations, such as &lt;a href="https://distribution.github.io/distribution/" rel="noopener noreferrer"&gt;CNCF Distribution&lt;/a&gt;, offer garbage-collection mechanisms to delete unreferenced blobs and free up storage space. However, for that to happen, old images (tags) referencing them have to be deleted first.&lt;/p&gt;

&lt;p&gt;There are implementations like &lt;a href="https://goharbor.io/" rel="noopener noreferrer"&gt;Harbor&lt;/a&gt;, which offer native retention policies for tags. However, if you host a registry like &lt;a href="https://distribution.github.io/distribution/" rel="noopener noreferrer"&gt;CNCF Distribution&lt;/a&gt;, you need additional tooling to automatically delete tags.&lt;/p&gt;
&lt;h2&gt;
  
  
  Regmaid
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/moritzrinow/regmaid" rel="noopener noreferrer"&gt;Regmaid&lt;/a&gt; is a simple CLI tool to enforce tag retention policies on Docker registries. It works entirely by communicating with the &lt;a href="https://docker-docs.uclv.cu/registry/spec/api/" rel="noopener noreferrer"&gt;Docker Registry HTTP API V2&lt;/a&gt;, making the functionality independent of registry implementation and storage backend.&lt;/p&gt;
&lt;h3&gt;
  
  
  How does it work?
&lt;/h3&gt;

&lt;p&gt;Regmaid inspects every image manifest behind every tag of a target repository to figure out the age of all images. It then deletes all tags matching a user-defined retention policy, allowing you to keep a min/max amount of tags and delete tags older than a specified period of time.&lt;/p&gt;
&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Define your registries and policies in a &lt;code&gt;regmaid.yaml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dockerCreds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="c1"&gt;# Use locally cached credentials from `docker login` &lt;/span&gt;

&lt;span class="na"&gt;registries&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dev&lt;/span&gt;
    &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;internal.registry.com&lt;/span&gt;
    &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;user&lt;/span&gt;
    &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;password&lt;/span&gt;

&lt;span class="na"&gt;policies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;example-app-dev&lt;/span&gt;
    &lt;span class="na"&gt;registry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dev&lt;/span&gt;
    &lt;span class="na"&gt;repository&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;example-app&lt;/span&gt; &lt;span class="c1"&gt;# Policies always target a single repository&lt;/span&gt;
    &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*-dev&lt;/span&gt; &lt;span class="c1"&gt;# Match tags ending with '-dev'&lt;/span&gt;
    &lt;span class="na"&gt;retention&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;30d&lt;/span&gt; &lt;span class="c1"&gt;# Delete tags older than 30 days&lt;/span&gt;
    &lt;span class="na"&gt;keep&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="c1"&gt;# Always keep at least newest 5 tags&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;If you do not specify &lt;code&gt;retention&lt;/code&gt;, the value of &lt;code&gt;keep&lt;/code&gt; represents the max. amount of tags that will be kept.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Regmaid can be installed via Go:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;go install github.com/moritzrinow/regmaid@latest
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run Regmaid with &lt;code&gt;dry-run&lt;/code&gt; to confirm it's working:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;regmaid -c regmaid.yaml --dry-run
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Regmaid will output all tags found eligible for deletion:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Processing policy "example-app-dev"...
Finished processing policy "example-app-dev"
Policy "example-app-dev" found 1/11 tags eligible for deletion:
0.1.0-dev (sha256:db38eb0ad0b317eba25b2d229d7b2af571961f6f2253bd223a11d48135e279fe) (55d)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, Regmaid can also be run with Docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;docker run -it -v /path/to/regmaid.yaml:/etc/regmaid/regmaid.yaml ghcr.io/moritzrinow/regmaid:latest
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After processing all policies, Regmaid will ask you to confirm the tag deletion. This can be skipped by providing the parameter &lt;code&gt;--yes&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automation
&lt;/h3&gt;

&lt;p&gt;For comfort reasons, Regmaid can be easily automated using tools like Cron or &lt;a href="https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/" rel="noopener noreferrer"&gt;CronJob&lt;/a&gt; on Kubernetes. An example of the latter one can be seen &lt;a href="https://github.com/moritzrinow/regmaid/blob/master/examples/kubernetes.yaml" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>registry</category>
      <category>regmaid</category>
      <category>kubernetes</category>
    </item>
  </channel>
</rss>
