Mark Ku's Blog

解決問題

因為 docker registry 發現用久了會硬碟不足,過去只要一陣子過後就要刪掉重建,因此我找寫了個腳本解決。

Docker 運行 registry ,要加上這參數 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 > 輸入

如果你想讓 Jenkins 的 Job 在每週日的 凌晨 3 點 執行,可以使用以下的 CRON 表達式:

0 3 * * 0  

0:秒數(固定為 0,因為不需要精確到秒)。
3:小時數,表示凌晨 3 點。
*:每天(不限制日期)。
*:每個月(不限制月份)。
0:星期天。

build periodically P.S. 想要什麼時間可以問chatgpt。

安裝Plugin - Pipeline Utility Steps

新增 Pipeline Job ,並撰寫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.")
                    }
                }
            }
        }
    }
}

作者

Mark Ku

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

覺得這篇有幫助?

作者做的免費工具、每日 Podcast 與電子報,都在這裡。

Mark Ku · 本文採用 CC BY 4.0 授權,轉載請註明作者並附上原文連結。

留言

訂閱電子報

訂閱後即時收到新文章通知,不錯過任何技術分享。

提交即表示同意接收電子報,隨時可

熱門文章

View all
Mark Ku
··604

Oracle Cloud 永久免費方案 Linux 主機及固定 IP :0 元打造雲端解決方案

Oracle Cloud 永久免費方案 Linux 主機及固定 IP :0 元打造雲端解決方案
Mark Ku
··471

告別 Postman 收費陷阱!開源 Git 原生 API 測試神器 Bruno 實戰指南

告別 Postman 收費陷阱!開源 Git 原生 API 測試神器 Bruno 實戰指南
Mark Ku
··329

一款免費開源類似於 Notion 類知識庫系統 — Outline Wiki 佈署與備份全攻略

一款免費開源類似於 Notion 類知識庫系統 — Outline Wiki 佈署與備份全攻略
Mark Ku
··240

打造高效 API 管理平台:從 0 開始部署 Kong Gateway - Part 1

打造高效 API 管理平台:從 0 開始部署 Kong Gateway - Part 1
Mark Ku
··235

訓練自己的 AI 語音:硬體門檻、開源模型比較與 LoRA 微調

訓練自己的 AI 語音:硬體門檻、開源模型比較與 LoRA 微調
Mark Ku
··216

在 Ubuntu 上設置 Samba 來共享資料夾,讓 Windows 11 用戶可以存取

在 Ubuntu 上設置 Samba 來共享資料夾,讓 Windows 11 用戶可以存取