在容器化部署的場景下,鏡像管理是一個很重要的部分,畢竟所有的程序都是以鏡像的方式來交付和運行的。
一個標準的鏡像名稱分爲三個部分:鏡像倉庫地址/鏡像存儲庫:鏡像版本,比如http://hub.docker.io/library/redis:1.0
鏡像倉庫地址:鏡像倉庫服務器的域名,比如docker官方鏡像倉庫http://hub.docker.io
鏡像存儲庫:鏡像的存儲名稱,官方名稱repository,比如library/redis
鏡像版本:鏡像的版本,官方名稱tag,比如1.0
衆所周知,docker鏡像是以分層來存儲鏡像的,而這個層是分倉庫管理的,比如library/redis下的層和private/redis下的層是分開管理的,通過docker registry的api獲取到的library/redis下的層在private/redis下是不存在的。
再介紹一下鏡像的pull和push過程:
pull操作:
- 先拉取清單文件
- 再拉取鏡像層
push操作:
- 先上傳所有層到倉庫
- 最後上傳清單文件
鏡像retag功能實現的原理就是利用了pull的拉取清單文件和push的上傳清單文件
通過上面的分析,在做鏡像的retag時,就需要考慮retag後的鏡像是否是同一個倉庫下的,如果是同一個repository下的retag操作,比如library/redis:1.0,在retag後成library/redis:1.1,那麼就表示是在同一個repository下,就不需要使用掛載操作,官方稱爲Cross Repository Blob Mount(交叉掛載層),如果library/redis:1.0在retag後變爲private/redis:1.0,由於不在同一個repository下,因此必須要進行mount操作纔行,不然在push清單文件的時候會報錯,具體步驟如下:
- 拉取library/redis:1.0的清單文件,相關的API:
GET /v2/<name>/manifests/<reference>
- 檢查清單文件中的層,如果retag的目標repository與第一步拉取的清單文件的repository不是同一個,進行mount層操作:
POST /v2/<name>/blobs/uploads/?mount=<digest>&from=<repository name>
- 上傳清單文件到目標repository中,完成retag
PUT /v2/<name>/manifests/<reference>
整個retag的過程就是這樣了。