用友雲開發者中心是基於Docker容器進行微服務架構應用的落地與管理。相信各位同窗在使用的過程當中,會發現隨着Docker鏡像的增多,佔用磁盤空間也約來越多。這時咱們須要清理私有鏡像倉庫中不須要的鏡像。但在實際操做時,纔會發現這本覺得很簡單的任務中卻暗藏玄機,遇到了很多的麻煩。在這裏咱們分享一下清理鏡像倉庫時遇到的坑點。想要直接尋求解決方案的同窗能夠直接看第二部分。git
1、那些年,咱們在清理鏡像倉庫時走過的坑github
坑點1:官方提供的接口並不能真正的刪除鏡像docker
這着實是最大的坑點。不少同窗查資料發現,官方已經提供了刪除鏡像倉庫的API,因此可能至關然的覺得直接使用就好,卻不知掉入了官方埋下的最大的坑點,也是本文要着手解決的核心問題:官方提供的刪除鏡像倉庫中鏡像的接口,僅僅是把manifest刪除了,真正的鏡像文件還存在!官方並無提供刪除鏡像層的接口!這也就是說,當咱們調用刪除鏡像的接口以後,僅僅是查看鏡像的列表時看不到原鏡像了,然而原有鏡像仍然在磁盤中,佔用着寶貴的文件存儲空間。json
坑點2:直接調用官方的刪除鏡像API,會返回405的錯誤碼緩存
直接調用刪除鏡像的接口,可能會遇到如下錯誤提示:安全
405,意味着方法不被容許。實際上,官方多是處於安全性的考慮,在默認的狀況下禁止了直接刪除鏡像的功能。若要開啓刪除鏡像功能,須要修改鏡像倉庫的配置文件。具體操做爲修改/etc/docker/registry/config.yml文件,在storage下添加delete的許可以後,重啓鏡像倉庫服務。架構
坑點3:使用官方提供的garbage-collect工具,會有無用的文件殘留app
官方爲registry提供了garbage-collect(gc)工具清理鏡像的物理存儲,將沒有引用的layer刪除。微服務
gc的清理過程分爲兩部分:工具
1)mark:掃描全部的manifest,列出引用的layer;
2)sweep:掃描全部的layer,不在mark裏的layer將被清理刪除。
gc能夠在dry-run的模式下運行(添加參數-d),只輸出gc信息,不進行實際操做。咱們能夠經過這種方式來確認哪些鏡像會被清除。
使用gc工具清理鏡像的一個問題就是文件清理得不夠乾淨,沒法清理已經沒有tag的鏡像目錄,而且還殘存少部分文件,從十KB到幾十KB不等。長此以往,垃圾文件和目錄的數量會愈來愈多。
坑點4:garbage-collect不是事務操做,清理鏡像時可能會產生誤操做
gc不是事務操做,當gc過程當中恰好有push操做時,則可能會誤刪數據。一個可行的解決辦法是手動更改鏡像倉庫的配置,暫時禁止鏡像的push操做。
在鏡像倉庫的配置文件中能夠配置read-only模式。當啓用read-only以後,再push鏡像時會獲得405的錯誤。gc完成後取消read-only模式,再push鏡像便可。
坑點5:使用garbage-collect工具後,必須重啓鏡像倉庫才能正常使用
若是不重啓鏡像倉庫,則再次push該鏡像時可能會獲得layer already exists錯誤:
其可能的緣由是鏡像被刪除後,倉庫的緩存中還存有已經刪除的鏡像信息,因此再次push會報層存在的錯誤。
2、兩種清理鏡像倉庫的方案
方案一:使用官方API + GC
使用官方提供的方法能夠較爲簡便的清理鏡像倉庫。整個清理過程可能須要幾百毫秒到幾秒的時間。此操做有必定的危險性,所以清理鏡像不宜過於頻繁。官方在git上也有相似描述。點擊查看:https://github.com/docker/docker-registry/issues/988
具體操做過程以下:
一、準備工做
在配置中許可刪除操做。修改鏡像倉庫的配置文件,通常在以下路徑:
/etc/docker/registry/config.yml
在storage下添加delete的許可以後,重啓鏡像倉庫。
用docker方式啓動的鏡像倉庫也能夠添加環境變量:
REGISTRY_STORAGE_DELETE_ENABLED=true
二、獲取待刪鏡像的digest
獲取鏡像digest的API爲:
GET /v2/<name>/manifests/<reference>
其中,name是倉庫名,reference是標籤,此時須要注意,調用時須要加上header內容:
Accept: application/vnd.docker.distribution.manifest.v2+json
其中Docker-Content-Digest的值就是鏡像的digest
三、調用官方的HTTP API V2刪除鏡像
刪除鏡像的API爲:
DELETE /v2/<name>/manifests/<reference>
其中,name是倉庫名稱,reference是包含「sha256:」的digest。
四、調用GC清理鏡像文件
使用gc工具的方式爲:
bin/registry garbage-collect /etc/docker/registry/config.yml
gc清理須要時間,若是在gc過程當中恰好有push操做,可能會產生未知的問題,建議設置read-only模式以後再進行gc,而後再改回來。
五、重啓docker registry
注意,若是不重啓會致使push相同鏡像時產生layer already exists錯誤。
方案二:使用第三方腳本
在清理鏡像倉庫這件事上,業內已經有不少人進行過各類各樣的嘗試。本文挑選一種比較好的方式推薦使用。
一、宿主機安裝delete-docker-registry-image
可參考此命令的安裝和使用方式。參考連接:https://github.com/burnettk/delete-docker-registry-image
二、執行delete-docker-registry-image命令能夠刪除某個倉庫(sb)
或者某個具體的鏡像(如alpine:3.2)
若是刪除某鏡像後該倉庫爲空,能夠用刪除倉庫的方式刪除此空倉。
該工具也提供了dry-run的方式,只輸出待刪除的信息不執行刪除操做。在命令後加上——dry-run便可。
三、重啓docker registry
跟gc方式同樣,刪除鏡像以後要重啓docker registry,否則仍是會出現相同鏡像push不成功的問題。
以上就是本文推薦的兩種清理鏡像倉庫的兩種方案。第一種方案更多的使用了官方提供的工具,使用時相對更加安全,且無需額外安裝其餘內容。第二種方案使用了第三方工具或腳本,使用時更加靈活且簡便,且清理的更加完全。具體操做時可根據本身的需求選擇方案。