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

