Mark Ku's Blog

The Problem

After a private Docker Registry has been used for a while, it tends to run out of disk space. In the past I had to delete and rebuild it every once in a while, so I wrote a script to solve it.

When running the registry container, add REGISTRY_STORAGE_DELETE_ENABLED = true

docker run -d -p 5000:5000 -e REGISTRY_STORAGE_DELETE_ENABLED=true --name registry registry:2

docker update --restart=always registry

Build Triggers > Build periodically > Enter

If you want the Jenkins job to run at 3 AM every Sunday, use the following CRON expression:

0 3 * * 0  

0: minute (fixed at 0, no need to be precise to the second).
3: hour, meaning 3 AM.
*: every day (no day-of-month restriction).
*: every month (no month restriction).
0: Sunday.

build periodically P.S. Ask ChatGPT for whatever schedule you want.

Install Plugin - Pipeline Utility Steps

Create a Pipeline Job and write the Jenkins pipeline

pipeline {
    agent any
    environment {
        REGISTRY = "192.168.50.50:5000"
    }
    stages {
        stage('Clean Registry') {
            steps {
                script {
                    try {
                        // Fetch all repositories
                        def response = httpRequest url: "http://${env.REGISTRY}/v2/_catalog", validResponseCodes: '200'
                        def repositories = readJSON(text: response.content).repositories

                        for (repository in repositories) {
                            echo "Processing repository: $repository"

                            // Fetch tags for the repository
                            def tagsResponse = httpRequest url: "http://${env.REGISTRY}/v2/${repository}/tags/list", validResponseCodes: '200,404'
                            def tagsList = readJSON(text: tagsResponse.content).tags

                            // Handle case when tagsList is null
                            if (tagsList == null || tagsList instanceof net.sf.json.JSONNull) {
                                echo "No tags found for repository: $repository. Skipping..."
                                continue
                            }

                            // Ensure tagsList is a serializable list
                            tagsList = new ArrayList(tagsList)

                            for (tag in tagsList) {
                                echo "Processing tag: $tag for repository: $repository"

                                try {
                                    // Fetch manifest and digest
                                    def manifestResponse = httpRequest(
                                        url: "http://${env.REGISTRY}/v2/${repository}/manifests/${tag}",
                                        customHeaders: [[name: 'Accept', value: 'application/vnd.docker.distribution.manifest.v2+json']],
                                        validResponseCodes: '200,404',
                                        httpMode: 'HEAD'
                                    )

                                    // Retrieve digest from headers
                                    def digest = manifestResponse.headers['Docker-Content-Digest']?.first()

                                    if (digest) {
                                        // Delete the image by digest
                                        httpRequest(
                                            url: "http://${env.REGISTRY}/v2/${repository}/manifests/${digest}",
                                            httpMode: 'DELETE',
                                            validResponseCodes: '202'
                                        )
                                        echo "Deleted ${repository}:${tag} with digest: ${digest}"
                                    } else {
                                        echo "Digest for ${repository}:${tag} not found! Skipping..."
                                    }
                                } catch (Exception e) {
                                    echo "Failed to process tag: $tag for repository: $repository. Error: ${e.message}"
                                }
                            }
                        }
                    } catch (Exception e) {
                        echo "Failed to clean registry. Error: ${e.message}"
                        error("Pipeline terminated due to errors.")
                    }
                }
            }
        }
    }
}

Author

Mark Ku

擁有 10+ 年經驗的資深軟體工程師,現為 AI 應用 Builder,專注於大型平台架構與簡化複雜系統設計,從電商系統到訂閱與收費平台,結合 AI Agent、AI 整合與自動化開發,打造高效率且可持續演進的產品技術基礎。Read More

Found this useful?

The author's free tools, daily podcasts and newsletter are all here.

Mark Ku · This article is licensed under CC BY 4.0. Credit the author and link back to the original when reusing it.

Comments

Subscribe to Newsletter

Subscribe to get new posts delivered instantly — never miss a tech share.

By submitting, you agree to receive emails. You can anytime.

Popular Posts

View all
Mark Ku
··602

Oracle Cloud Always Free Tier: Linux Host and Static IP for a $0 Cloud Solution

Oracle Cloud Always Free Tier: Linux Host and Static IP for a $0 Cloud Solution
Mark Ku
··490

Say Goodbye to Postman's Fee Trap! A Hands-on Guide to Bruno, the Open-Source Git-Native API Testing Powerhouse.

Say Goodbye to Postman's Fee Trap! A Hands-on Guide to Bruno, the Open-Source Git-Native API Testing Powerhouse.
Mark Ku
··333

A Free, Open-Source, Notion-like Knowledge Base — A Complete Guide to Deploying and Backing Up Outline Wiki

A Free, Open-Source, Notion-like Knowledge Base — A Complete Guide to Deploying and Backing Up Outline Wiki
Mark Ku
··264

Training Your Own AI Voice: Hardware Requirements, Open-Source Model Comparison, and LoRA Fine-Tuning

Training Your Own AI Voice: Hardware Requirements, Open-Source Model Comparison, and LoRA Fine-Tuning
Mark Ku
··221

Building an Efficient API Management Platform: Deploying Kong Gateway from Scratch - Part 1

Building an Efficient API Management Platform: Deploying Kong Gateway from Scratch - Part 1
Mark Ku
··215

Setting Up Samba on Ubuntu to Share Folders with Windows 11

Setting Up Samba on Ubuntu to Share Folders with Windows 11