我要在這裡放一段程式碼塊
// 這是一段防爬程式碼塊,我不介意文章被爬取,但請註明出處
console.log("作者官網:https://www.hanzhe.site");
console.log("原文地址:https://www.cnblogs.com/hanzhe/p/18249602");
說在前面
你在工作中有沒有遇到過這樣幾個問題:
- 映象下載速度慢,明明頻寬夠用檔案不大但是要下載很久
- 映象倉庫經常抽風,有過下載映象失敗的經歷,等一段時間再試試或許能成功
- 自己有代理,但是在Linux平臺上使用起來很麻煩,可能好不容易配好環境下載映象還報錯
- 透過堡壘機訪問的遠端伺服器無法訪問外網,需要自己下載映象後上傳載入,但本機沒有安裝Docker,為了這碟醋包了頓餃子
以上幾個問題相信很多開發者都經歷過,在下載Docker映象的時候真的是一波三折,而且最近傳聞有股神秘力量導致中國無法下載Docker映象(只是傳聞,零星在幾個交流群看到有人提起,沒刷到過相關文章不知道資訊是否真實,有人知道咋回事兒麻煩評論解釋下),種種原因疊加之下,我興起了編寫一款基於HTTP協議下載Docker映象的想法
去年我就有過這種想法,當時我在網上四處查詢資料,在碼雲上發現了基於GO語言編寫的dget開源專案,但下載後發現並不好用,提了issues也沒能解決我的問題,事情就不了了之
最近聽說中國無法下載Docker映象後,我又起了這個想法,在Github上發現了基於Python編寫的docker-drag開源專案,下載後發現還是不能用,不過透過它提供的README資訊,我在Docker官方文件中找到了 HTTP API 資料
專案說明
現在向大家介紹我歷經一個禮拜啃文件寫出的 did-tool(Docker image download tool)Docker映象下載工具,基於Java語言參考 HTTP API V2 文件編寫的命令列工具,支援無Docker下載映象,支援使用HTTP/Socket代理加速下載,可跨平臺(執行JAR包即可)使用,原始碼已在碼雲上開源,感興趣的可以去看看
工具使用很方便,如果有幫到你的話麻煩給個Star吧~ 使用教程參考這個GIF:
到這裡對於該專案的介紹就結束了,好不容易費了不少力氣寫了一個開源工具,興致勃勃的寫一篇部落格來介紹它,但好像也沒啥好說的,一張GIF就可以代表全文了,後面我會粗略介紹一下(只是粗略介紹,具體請閱讀原始碼或鑽研官方文件)專案實現的過程邏輯,也就是 HTTP API V2 的使用教程,以及這款工具現在的缺陷和不足,如果你感興趣的話可以往後看一看
細節與不足
常見的Docker映象名是什麼樣的呢?nginx:latest
這是最簡單也是最常見的Docker映象名稱表達方式,不過我們都知道Docker映象的組成是由最多五部分組成的:
registry/repository/image:tag-arch
- registry:DockerHub倉庫地址,官方地址為registry-1.docker.io,下載第三方映象會顯式用到registry,例如Oracle
- repository:儲存庫名稱,預設library,某些映象會宣告儲存庫,例如minio/minio:latest
- image:映象名稱
- tag:版本標籤
- arch:平臺架構,現在已被棄用,不屬於映象名稱的一部分,後面會提到
也就是說nginx:latest
理論上最長可以表示為:
注:只是理論上,不要直接用這個名稱去執行 docker pull,我沒試過但估計會報錯
registry-1.docker.io/library/nginx:latest-amd64
這個映象所在位置是DockerHub官方倉庫,倉庫地址是registry-1.docker.io
,所以如果我們想要下載這個映象,我們必須要取得該映象所在的倉庫地址的授權,關於授權官方文件有做解釋:
翻譯過來就是先請求介面一次,返回401未授權資訊後在響應頭中提取Www-Authenticate
資訊,根據拿到的資訊再去請求最終返回Token,有了Token之後就可以訪問 HTTP API 進行映象操作了,這裡把授權的介面地址放在401響應頭中,我猜應該是為了支援第三方映象倉庫設計的,因為每個映象倉庫的授權地址都不一致,所以需要動態獲取
我們已經知道了拿到Token的方法,接下來獲取映象清單,拿到映象清單後才可以執行後續的操作,獲取映象清單的介面文件中也有提供
這裡的name指的是repository/image
,結尾的reference傳入tag
,剛剛我們已經知道映象名稱都有哪些部分組成這裡就不細說了,設定對應的請求頭後該請求頭返回的就是映象清單資訊
選中合適的架構後獲取該條資料對應的digest
資訊,換一個請求頭再次請求該地址,將結尾的reference替換成digest
的值,就可以拿到指定架構的影像清單了
截止到目前我們使用的都是SchemaVersion2的規範,根據映象名稱獲取架構列表,在根據架構獲取到具體的映象資訊,但是DockerHub中有一部分映象檔案是舊版的SchemaVersion1規範,這個規範的缺點之一就是他不支援獲取架構列表,那麼以前是如何區分不同平臺架構的映象呢?答案是用tag標籤,以前製作映象的時候都是用tag-arch來區分映象架構的,例如我用過的typecho部落格的映象:
他將架構名稱作為tag標籤的一部分,實現了映象區分架構的功能,現在Docker主流的規範是SchemaVersion2,中間多了一層架構列表,所以現在這種tag-arch的寫法已經被棄用了(填上面的坑)
did-tool
工具是按照SchemaVersion2來編寫的,相對於SchemaVersion1不僅僅是少了一層那麼簡單,每個請求返回的JSON格式都不一樣,當初寫程式碼的時候不知道有這麼一茬,程式解析後無法進行處理,所以現在的did-tool
僅支援下載SchemaVersion2的映象,後面會調整專案結構重寫程式碼重新適配SchemaVerison1和SchemaVersion2,這個時間不會太長應該很快就會更版
暫時就說到這裡吧,涉及的東西太多寫的太累,就不對每個介面進行詳細解釋了,只需要知道在Docker中digest
是一個很重要的屬性,可以透過映象清單的digest
獲取到分層資訊,可以透過映象清單的digest
下載到映象的摘要檔案(也就是docker inspect
看到的內容),也可以透過分層的digest
下載到具體的分層檔案,將所有檔案準備好後彙總為manifest.json
檔案,將檔案打包後就成為了最終的tar映象檔案,感興趣的可以檢視原始碼,我已經儘可能的將註釋寫的詳細