Docker映象下載慢/失敗?Linux代理使用不便?想無Docker下載映象?試試我這款開源專案吧

Java小学生丶發表於2024-06-16

我要在這裡放一段程式碼塊

// 這是一段防爬程式碼塊,我不介意被文章被爬取,但請註明出處
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
  • image:映象名稱
  • tag:版本標籤
  • arch:平臺架構,現在已被棄用,不屬於映象名稱的一部分,後面會提到

也就是說nginx:latest理論上最長可以表示為:

注:只是理論上,不要直接用這個名稱去執行 docker pull,我沒試過但估計會報錯
registry-1.docker.io/library/nginx:latest-amd64

這個映象所在位置是DockerHub官方倉庫,倉庫地址是registry-1.docker.io,所以如果我們想要下載這個映象,我們必須要取得該映象所在的倉庫地址的授權,關於授權官方文件有做解釋:

image

翻譯過來就是先請求介面一次,返回401未授權資訊後在響應頭中提取Www-Authenticate資訊,根據拿到的資訊再去請求最終返回Token,有了Token之後就可以訪問 HTTP API 進行映象操作了,這裡把授權的介面地址放在401響應頭中,我猜應該是為了支援第三方映象倉庫設計的,因為每個映象倉庫的授權地址都不一致,所以需要動態獲取

我們已經知道了拿到Token的方法,接下來獲取映象清單,拿到映象清單後才可以執行後續的操作,獲取映象清單的介面文件中也有提供

image

這裡的name指的是repository/image,結尾的reference傳入tag,剛剛我們已經知道映象名稱都有哪些部分組成這裡就不細說了,設定對應的請求頭後該請求頭返回的就是映象清單資訊

image

選中合適的架構後獲取該條資料對應的digest資訊,換一個請求頭再次請求該地址,將結尾的reference替換成digest的值,就可以拿到指定架構的影像清單了

image

截止到目前我們使用的都是SchemaVersion2的規範,根據映象名稱獲取架構列表,在根據架構獲取到具體的映象資訊,但是DockerHub中有一部分映象檔案是舊版的SchemaVersion1規範,這個規範的缺點之一就是他不支援獲取架構列表,那麼以前是如何區分不同平臺架構的映象呢?答案是用tag標籤,以前製作映象的時候都是用tag-arch來區分映象架構的,例如我用過的typecho部落格的映象:

image

他將架構名稱作為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映象檔案,感興趣的可以檢視原始碼,我已經儘可能的將註釋寫的詳細

image

相關文章