Docker鏡像倉(cāng)庫(kù)的垃圾回收機(jī)制深度清理后端存儲(chǔ)空間的實(shí)現(xiàn)
Docker 鏡像倉(cāng)庫(kù)的垃圾回收(Garbage Collection, GC)機(jī)制是管理后端存儲(chǔ)空間的核心手段。其本質(zhì)是通過(guò)標(biāo)記-清除(Mark and Sweep)算法,識(shí)別并刪除不再被任何鏡像清單(Manifest)引用的 Blob(鏡像層和配置對(duì)象),從而真正釋放磁盤空間。
一、GC 的核心原理:標(biāo)記-清除兩階段
1. Marking 階段(標(biāo)記)
GC 掃描所有倉(cāng)庫(kù)(repositories)下的 tags 目錄,讀取 link 文件獲取 manifest 摘要(digest)。隨后遍歷每個(gè) manifest,提取其中引用的所有 layer 和 config 文件的 digest,將這些 Blob 標(biāo)記為"存活"(不可刪除)。
2. Sweep 階段(清除)
遍歷整個(gè) blobs 目錄下的所有 Blob。若某個(gè) Blob 的 digest 不在標(biāo)記集合中,則將其加入刪除集合并執(zhí)行物理刪除。
流程示意:
開始 GC → 掃描所有 Manifest → 標(biāo)記引用的 Blobs → 遍歷所有 Blobs
↓
是否被標(biāo)記?
是 → 保留 否 → 刪除二、為什么必須手動(dòng)/定時(shí)觸發(fā) GC?
Docker Registry 的設(shè)計(jì)遵循內(nèi)容尋址存儲(chǔ)(CAS)原則,多個(gè)鏡像標(biāo)簽可能共享相同的底層 layer。因此:
- 刪除 tag 僅移除引用:當(dāng)你刪除一個(gè)鏡像標(biāo)簽時(shí),只是刪除了 manifest 的引用記錄,底層的 blob 文件仍然保留。
- 共享 layer 保護(hù):如果某個(gè) layer 仍被其他鏡像引用,GC 不會(huì)刪除它,避免破壞其他鏡像。
- 空間不會(huì)自動(dòng)釋放:Registry 不會(huì)自動(dòng)運(yùn)行 GC,必須手動(dòng)觸發(fā)或使用定時(shí)任務(wù)。
三、執(zhí)行 GC 的標(biāo)準(zhǔn)操作
前置條件
Registry 配置必須開啟刪除功能:
storage:
delete:
enabled: true基礎(chǔ) GC 命令
# 進(jìn)入 Registry 容器執(zhí)行 docker exec registry bin/registry garbage-collect /etc/docker/registry/config.yml # 同時(shí)清理未被任何標(biāo)簽引用的 manifest(推薦) docker exec registry bin/registry garbage-collect --delete-untagged /etc/docker/registry/config.yml # 僅模擬運(yùn)行,不實(shí)際刪除(用于驗(yàn)證) docker exec registry bin/registry garbage-collect --dry-run /etc/docker/registry/config.yml
安全實(shí)踐:只讀模式下運(yùn)行
GC 期間必須禁止寫入,否則可能導(dǎo)致數(shù)據(jù)競(jìng)爭(zhēng)和損壞:
#!/bin/bash # 將 Registry 切換為只讀模式 docker exec registry sh -c 'sed -i "s/readonly: false/readonly: true/" /etc/docker/registry/config.yml && kill -HUP 1' sleep 5 # 執(zhí)行 GC docker exec registry bin/registry garbage-collect /etc/docker/registry/config.yml --delete-untagged # 恢復(fù)寫入 docker exec registry sh -c 'sed -i "s/readonly: true/readonly: false/" /etc/docker/registry/config.yml && kill -HUP 1'
四、深度清理:處理頑固空間占用
場(chǎng)景 1:手動(dòng)刪除倉(cāng)庫(kù)后 GC 效果不佳
如果直接刪除了 repositories 目錄下的命名空間,但 GC 釋放空間很少,原因是:
只要 repositories 目錄中的名稱空間存在,其下的 blob 文件就不會(huì)被回收。
解決方案:
# 1. 先刪除 repositories 中的元數(shù)據(jù)目錄 cd /var/lib/registry/docker/registry/v2/repositories && rm -rf <namespace> # 2. 再執(zhí)行 GC docker exec registry bin/registry garbage-collect /etc/docker/registry/config.yml
場(chǎng)景 2:清理過(guò)期的 Tags 和 Revisions
對(duì)于長(zhǎng)期運(yùn)行的 Registry,可以定期清理舊的 tag 和 manifest revision:
# 刪除 14 天未更新的 tag 目錄
find /var/lib/registry/docker/registry/v2/repositories/*/_manifests/tags/* \
-type d -mtime +14 -maxdepth 1 -exec rm -rf {} \;
# 刪除 14 天前的未引用 manifest revision
find /var/lib/registry/docker/registry/v2/repositories/*/_manifests/revisions/sha256/* \
-type d -mtime +14 -maxdepth 1 -exec rm -rf {} \;
# 最后執(zhí)行 GC
docker exec registry bin/registry garbage-collect -m /etc/docker/registry/config.yml場(chǎng)景 3:清理空目錄
GC 后可能殘留空目錄,占用 inode:
# 刪除 blobs/sha256 下的空目錄
for dir in $(find /var/lib/registry/docker/registry/v2/blobs/sha256/ -type d -empty); do
rm -rf "$dir"
done五、企業(yè)級(jí)方案:Harbor 的自動(dòng) GC
對(duì)于生產(chǎn)環(huán)境,建議使用 Harbor 替代原生 Registry。Harbor 提供:
- Web UI 一鍵刪除:刪除 tag 后自動(dòng)標(biāo)記 manifest
- 定時(shí) GC 任務(wù):在管理界面配置自動(dòng)垃圾回收計(jì)劃
- 保留策略:基于鏡像年齡、標(biāo)簽?zāi)J降茸詣?dòng)清理
六、定時(shí)自動(dòng)化腳本示例
#!/bin/bash
# /opt/registry/registry-cleanup.sh
REGISTRY_CONTAINER="registry"
REGISTRY_HOME="/var/lib/registry/docker/registry/v2"
LOG="/var/log/registry-cleanup.log"
echo "[$(date)] Starting cleanup..." >> $LOG
# 1. 清理過(guò)期 tags(>30 天)
find ${REGISTRY_HOME}/repositories/*/_manifests/tags/* \
-type d -mtime +30 -maxdepth 1 -exec rm -rf {} \; 2>/dev/null
# 2. 清理過(guò)期 revisions
find ${REGISTRY_HOME}/repositories/*/_manifests/revisions/sha256/* \
-type d -mtime +30 -maxdepth 1 -exec rm -rf {} \; 2>/dev/null
# 3. 切換只讀模式
docker exec $REGISTRY_CONTAINER sh -c \
'sed -i "s/readonly: false/readonly: true/" /etc/docker/registry/config.yml && kill -HUP 1'
sleep 5
# 4. 執(zhí)行 GC
docker exec $REGISTRY_CONTAINER bin/registry garbage-collect \
--delete-untagged /etc/docker/registry/config.yml >> $LOG 2>&1
# 5. 恢復(fù)寫入
docker exec $REGISTRY_CONTAINER sh -c \
'sed -i "s/readonly: true/readonly: false/" /etc/docker/registry/config.yml && kill -HUP 1'
# 6. 清理空目錄
find ${REGISTRY_HOME}/blobs/sha256/ -type d -empty -delete 2>/dev/null
echo "[$(date)] Cleanup completed." >> $LOGCrontab 配置(每月 1 日和 15 日凌晨 2:30 執(zhí)行):
30 2 1,15 * * /opt/registry/registry-cleanup.sh
七、關(guān)鍵注意事項(xiàng)
| 風(fēng)險(xiǎn)點(diǎn) | 說(shuō)明 |
|---|---|
| 必須只讀運(yùn)行 | GC 期間任何 push 操作都可能導(dǎo)致數(shù)據(jù)損壞 |
| 先 dry-run | 首次清理前使用 --dry-run 預(yù)覽刪除內(nèi)容 |
| 共享 layer 保護(hù) | GC 不會(huì)刪除仍被引用的 blob,這是正常行為 |
| 大倉(cāng)庫(kù)性能 | 超大規(guī)模 Registry 的 GC 可能耗時(shí)數(shù)小時(shí),可考慮增量 GC 方案 |
| 備份優(yōu)先 | 執(zhí)行前備份 /var/lib/registry 目錄,防止誤刪 |
通過(guò)理解 Registry 的引用計(jì)數(shù)機(jī)制,并結(jié)合定期清理 tags、revisions 與 GC 的完整流程,可以有效控制后端存儲(chǔ)空間的持續(xù)增長(zhǎng)。
到此這篇關(guān)于Docker鏡像倉(cāng)庫(kù)的垃圾回收機(jī)制深度清理后端存儲(chǔ)空間的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Docker垃圾回收清理后端存儲(chǔ)空間內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Docker 安裝 LogStash的詳細(xì)過(guò)程
Logstash,作為Elastic Stack家族中的核心成員之一,是一個(gè)功能強(qiáng)大的開源數(shù)據(jù)收集引擎,在本文中,我們將詳細(xì)介紹如何借助Docker容器技術(shù)快速安裝配置Logstash,以實(shí)現(xiàn)日志及各類事件數(shù)據(jù)的無(wú)縫集成與實(shí)時(shí)處理,感興趣的朋友一起看看吧2024-03-03
在Docker容器中部署靜態(tài)網(wǎng)頁(yè)的方法教程
這篇文章主要給大家介紹了在Docker容器中部署靜態(tài)網(wǎng)頁(yè)的方法教程,文中介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-06-06
在CentOS 7上安裝Docker環(huán)境的方法與注意事項(xiàng)
這篇文章主要介紹了在CentOS 7上安裝Docker環(huán)境的方法與注意事項(xiàng),需要的朋友可以參考下2016-10-10
docker?registry刪除遠(yuǎn)程倉(cāng)庫(kù)鏡像實(shí)現(xiàn)方式
文章介紹如何清理Docker?Registry中堆積的鏡像,通過(guò)配置刪除功能、啟動(dòng)容器、查看鏡像信息并執(zhí)行刪除操作,同時(shí)提供基于web-ui的管理方案,優(yōu)化存儲(chǔ)空間使用2025-09-09
Docker容器Container鏡像Image如何存儲(chǔ)詳解
本文主要介紹Docker容器(Container)和鏡像(Image)是如何進(jìn)行數(shù)據(jù)存儲(chǔ)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09
Docker啟動(dòng)容器報(bào)錯(cuò):Ports are not available的解決方案
這篇文章主要介紹了Docker啟動(dòng)容器報(bào)錯(cuò):Ports are not available的解決方案,Docker 將容器程序的端口號(hào)映射到宿主機(jī)的端口號(hào),是一個(gè) NAT 過(guò)程,這個(gè)過(guò)程可能會(huì)因?yàn)榕c Windows NAT 服務(wù)沖突而失效,文中有詳細(xì)的解決方案,需要的朋友可以參考下2024-03-03

