<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何構(gòu)建私有 Docker Hub 鏡像站

          共 6076字,需瀏覽 13分鐘

           ·

          2021-09-19 13:41

          自去年 11 月份開(kāi)始,Docker 公司為了降低運(yùn)營(yíng)成本對(duì) Docker Hub 上 pull 鏡像的策略進(jìn)行了限制,本文介紹了構(gòu)建私有 Docker Hub 鏡像站的方式,可將 Docker Hub 上的 library repo 的鏡像同步到本地鏡像倉(cāng)庫(kù)。

          作者:木子(才云)

          編輯:Sarah(K8sMeetup)

          K8sMeetup
          Docker Hub 限制
          自從去年 11 月份開(kāi)始,Docker 公司為了降低運(yùn)營(yíng)成本就對(duì) Docker Hub 上 pull 鏡像的策略進(jìn)行了如下限制:
          • 未登錄用戶(hù),每 6 小時(shí)只允許 pull 100 次
          • 已登錄用戶(hù),每 6 小時(shí)只允許 pull 200 次
          而且,限制的手段也非常地粗暴,通過(guò)判斷請(qǐng)求鏡像的 manifest 文件的次數(shù)。請(qǐng)求一個(gè)鏡像的 manifest 文件就算作一次 pull 鏡像。即便是 pull 失敗了,也會(huì)算作一次。隨后也有很多大佬分享繞過(guò) Docker Hub 限制的辦法,比如搭建私有的鏡像倉(cāng)庫(kù),然后再給客戶(hù)端配置上 registry-mirrors 參數(shù),就可以通過(guò)本地的鏡像倉(cāng)庫(kù)來(lái)拉取鏡像。
          • 突破 Docker Hub 限制,全鏡像加速服務(wù):https://moelove.info/2020/09/20/%e7%aa%81%e7%a0%b4-DockerHub-%e9%99%90%e5%88%b6%e5%85%a8%e9%95%9c%e5%83%8f%e5%8a%a0%e9%80%9f%e6%9c%8d%e5%8a%a1/
          • 繞過(guò)從 Docker Hub pull 鏡像時(shí)的 429 toomanyrequests:https://nova.moe/bypass-docker-hub-429/
          • 如何繞過(guò) Docker Hub 拉取鏡像限制:https://www.chenshaowen.com/blog/how-to-cross-the-limit-of-dockerhub.html
          但是以上方法都比較局限:
          • 首先鏡像需要挨個(gè)手動(dòng) push 到本地鏡像倉(cāng)庫(kù);
          • 其次本地鏡像倉(cāng)庫(kù)中的鏡像無(wú)法和官方鏡像保持同步更新,如果要使用新的 tag 好的鏡像仍然需要手動(dòng)將鏡像從 Docker Hub 上 pull 下來(lái),然后再 push 到本地鏡像倉(cāng)庫(kù);
          • 還有手動(dòng) push 鏡像是比較混亂的,如果使用的鏡像比較多,比如公有云容器服務(wù),這時(shí)候再手動(dòng) push 的話(huà)管理起來(lái)是極其不方便的。
          因此經(jīng)過(guò)一番折騰終于摸索出了一個(gè)方案,將 Docker Hub 上 library repo 的鏡像同步到本地鏡像倉(cāng)庫(kù),最終做到上游如果更新了鏡像 tag 也能自動(dòng)地將鏡像同步到本地鏡像倉(cāng)庫(kù)
          K8sMeetup
          獲取鏡像 tag
          對(duì)于 Docker Hub 上的鏡像,我們使用到最多的就是 library 這個(gè) repo 即 Official Images on Docker Hub(https://docs.docker.com/docker-hub/official_images/),里面包含大部分開(kāi)源軟件和 Linux 發(fā)行版的基礎(chǔ)鏡像。
          • Provide essential base OS repositories (for example, ubuntu, centos) that serve as the starting point for the majority of users.
          • Provide drop-in solutions for popular programming language runtimes, data stores, and other services, similar to what a Platform as a Service (PAAS) would offer.
          • Exemplify Dockerfile best practices and provide clear documentation to serve as a reference for other Dockerfile authors.
          • Ensure that security updates are applied in a timely manner. This is particularly important as Official Images are some of the most popular on Docker Hub.
          library 的鏡像常見(jiàn)的特點(diǎn)就是當(dāng)我們使用 docker 客戶(hù)端去 pull 一個(gè)鏡像時(shí),無(wú)需指定該鏡像的 repo ,比如 ubuntu:latest,其他非 library 的鏡像需要指定鏡像所屬的 repo,比如 jenkins/slave:latest。這部分代碼是硬編碼在 docker 的源碼當(dāng)中的。
          我們雖然日常訪問(wèn)的是 https://hub.docker.com ,但是我們?cè)?https://github.com/docker/distribution/blob/master/reference/normalize.go#L13 中可以看到實(shí)際 docker 使用的地址是一個(gè)硬編碼的 docker.io

          我們可以通過(guò)如下幾種辦法來(lái)獲取 Docker Hub 上 library repo 的鏡像列表。
          通過(guò) docker registry 命令行
          在 Docker 官方文檔中 docker registry 有提到可以列出某個(gè) registry 中的鏡像,但這個(gè)功能僅限于 Docker Enterprise Edition. 版本,而社區(qū)的版本中未有該命令。遂放棄……

          通過(guò) registry v2 API
          • get-images.list

          通過(guò) Docker Hub 的 API 獲取到的鏡像 tag 實(shí)在是太多了,截至今日 Docker Hub 上整個(gè) library repo 的項(xiàng)目一共有 162 個(gè),而這 162 個(gè)項(xiàng)目中的鏡像 tag 數(shù)量多達(dá)五萬(wàn)兩千多個(gè)。總的鏡像倉(cāng)庫(kù)存儲(chǔ)占用空間的大小預(yù)計(jì)至少 5TB。其中的鏡像我們真正需要用到的估計(jì)也不到 0.1%,因此需要想個(gè)辦法減少這個(gè)鏡像列表的數(shù)量,獲得的鏡像列表更精確一些,通用一些。

          通過(guò) official-images repo
          以 Debian 為例,在 Docker Hub 上鏡像的 tag 基本上都是這樣子的:
          Supported tags and respective Dockerfile links
          • bullseye, bullseye-20210208
          • bullseye-backports
          • bullseye-slim, bullseye-20210208-slim
          • buster, buster-20210208, 10.8, 10, latest
          • buster-backports
          • buster-slim, buster-20210208-slim, 10.8-slim, 10-slim
          • experimental, experimental-20210208
          • jessie, jessie-20210208, 8.11, 8
          • jessie-slim, jessie-20210208-slim, 8.11-slim, 8-slim
          每一行都代表著同一個(gè)鏡像,如:buster, buster-20210208, 10.8, 10, latest。一行中鏡像雖然有多個(gè) tag,但這些 tag 指向的 manifest 其實(shí)都是一致的。鏡像 tag 的關(guān)系有點(diǎn)類(lèi)似于 C 語(yǔ)言里的指針變量,是引用的關(guān)系。
          但這么多的信息是如何高效地管理的呢?于是順藤摸瓜發(fā)現(xiàn)了:library repo 里的鏡像構(gòu)建信息都是由 official-images 這個(gè) repo 來(lái)管理的。

          在這個(gè) official-images repo 里 library 目錄下有以鏡像 name 命名的文件,而文件的內(nèi)容記錄著與 Docker Hub 相對(duì)應(yīng)的 tag 信息。由此我們可以根據(jù)這個(gè) repo 獲取 library repo 鏡像的 tag。好處在于雖然這樣得到的鏡像列表并不是全面的,但這個(gè) repo 里記錄的鏡像 tag 都是官方還在維護(hù)的,并不會(huì)包含一些舊的或者 CI 測(cè)試的鏡像。這樣獲得的鏡像列表更通用一些。
          拿出 Linux 文本處理三劍客,一頓操作搓出了個(gè)腳本來(lái)生成鏡像以及鏡像的數(shù)量。驚奇的發(fā)現(xiàn),通過(guò)這種方式獲取到的鏡像數(shù)量為 Docker Hub 的 registry API 獲取到的鏡像數(shù)量的十分之一左右。根據(jù)如下數(shù)據(jù)可以得出,Docker Hub 真實(shí)需要的鏡像數(shù)量為 1517 個(gè),而 5590 個(gè)鏡像中包含了多個(gè) tag 指向同一個(gè)鏡像的情況,因此,我們只需要將這些相同鏡像的 tag pull 一次即可,其余的鏡像通過(guò) retag 的方式打上 tag 即可。

          K8sMeetup
          本地同步鏡像
          獲取到鏡像列表之后,我們就可用使用 skopeo copy 直接將鏡像 copy 到本地的鏡像倉(cāng)庫(kù)中啦。結(jié)合上述步驟,使用不到 20 行的腳本就能完成:

          但事情沒(méi)我想象中的那么簡(jiǎn)單,在自己的機(jī)器上 pull 了不到 150 個(gè)鏡像的時(shí)候就報(bào)錯(cuò)退出了,提示 toomanyrequests: You have reached your pull rate limit. 錯(cuò)誤。
          ime=”2021-02-12T07:08:51Z” level=fatal msg=”Error parsing image name "docker://ubuntu:latest":
          Error reading manifest latest in docker.io/library/ubuntu: toomanyrequests: You have reached your pull rate limit. You may increase the limit by authenticating and upgrading: https://www.docker.com/increase-rate-limit"
          K8sMeetup
          GitHub Actions 同步鏡像
          SSH 連接 runner
          在剛開(kāi)始寫(xiě)這篇博客的時(shí)候也沒(méi)有想到使用 GitHub Actions,在刷 GitHub 動(dòng)態(tài)的時(shí)候無(wú)意間發(fā)現(xiàn)了它,于是又一頓操作看看 GitHub Actions 是否能用來(lái)同步鏡像。
          首先參考 SSH 連接到 GitHub Actions 虛擬服務(wù)器連接到 runner 的機(jī)器上:
          • .github/workflows/ssh.yaml

          使用 SSH 連接到 action runner 的機(jī)器里意外發(fā)現(xiàn),在 ~/.docker/config.json 文件里竟然已經(jīng)有了個(gè) login 的 Docker Hub 賬戶(hù)。哦豁.jpg。由于 docker login 的配置文件只是簡(jiǎn)單的 base64 加密,解碼后拿到真實(shí)的 user 和 token。

          于是想著可以驗(yàn)證一下這個(gè)賬戶(hù)是否有限制:

          但失敗了,提示 {"details":"incorrect username or password"}。估計(jì)這個(gè)賬戶(hù)是個(gè) bot 賬戶(hù),只能用于 pull 鏡像,其他的 API 請(qǐng)求都沒(méi)權(quán)限使用。至于這個(gè)賬戶(hù)有沒(méi)有限制,還需要做下測(cè)試。
          另外意外地發(fā)現(xiàn) runner 的機(jī)器里集成了很多工具,其中 skopeo 也包含在內(nèi),實(shí)在是太方便了。我們就使用 skopeo inspect 去請(qǐng)求鏡像的 manifests 文件,看看最多能請(qǐng)求多少會(huì)被限制。于是花了點(diǎn)時(shí)間搓了個(gè)腳本用于去獲取 Docker Hub 上 library repo 中的所有鏡像的 manifests 文件。
          • get-manifests.sh

          經(jīng)過(guò)一番長(zhǎng)時(shí)間的測(cè)試,在獲取了 20058 個(gè)鏡像的 manifest 文件之后依舊沒(méi)有被限制,于是大膽猜測(cè),runner 里內(nèi)置的 Docker Hub 賬戶(hù) pull library 鏡像是沒(méi)有限制的。估計(jì)是 GitHub 和 docker inc 達(dá)成了 py 交易,用這個(gè)賬戶(hù)去 pull 公共鏡像沒(méi)有限制。

          定時(shí)同步鏡像
          從上述步驟一可知,在 GitHub Actions runner 機(jī)器里自帶的 docker login 賬戶(hù)沒(méi)有限制,那我們最終就選定使用它來(lái)同步鏡像到本地 registry 吧。參照 GitHub Actions 照葫蘆畫(huà)瓢搓了個(gè) action 的配置文件:

          增量同步
          默認(rèn)設(shè)置的為 6 小時(shí)同步一次上游最新的代碼,由于定時(shí)更新是使用的增量同步,即通過(guò) git diff 的方式將當(dāng)前分支最新的 commit 和上游 Docker Hub 官方的 repo 最新 commit 進(jìn)行比較,找出變化的鏡像。因此如果是首次同步,需要全量同步,在同步完成之后會(huì)給 repo 打上一個(gè)時(shí)間戳的 tag ,下次同步的時(shí)候就用這個(gè) tag 和上游 repo 最新 commit 做差異比較。

          K8sMeetup

          如何食用?

          如果你也想將 Docker Hub 上 library repo 的鏡像搞到本地鏡像倉(cāng)庫(kù),可以參考如下方法:
          勸退三連??
          • 鏡像倉(cāng)庫(kù)建議使用 docker registry 或者 harbor,具體的部署方法可以在互聯(lián)網(wǎng)上找到。
          • 需要個(gè)大盤(pán)雞(大硬盤(pán)機(jī)器),當(dāng)前 Docker Hub 上還在維護(hù)的 tag 鏡像總大小為 128 GB 左右。
          • 如果是長(zhǎng)期使用,本地鏡像倉(cāng)庫(kù)的存儲(chǔ)空間至少 1TB 以上。
          • 由于是使用 GitHub Actions 的機(jī)器將鏡像 push 到本地鏡像倉(cāng)庫(kù),因此本地鏡像倉(cāng)庫(kù)需要有個(gè)公網(wǎng) IP
          增加配置
          首先 fork 官方的 repo docker-library/official-images 到自己的 GitHub 賬戶(hù)下,然后 fork 這個(gè) repo muzi502/sync-library-images 到自己的 GitHub 賬戶(hù)下,最后在自己的 sync-library-images 這個(gè) repo 的 Settings > Secrets 中配置好如下三個(gè)變量:
          • REGISTRY_DOMAIN 設(shè)置為本地鏡像倉(cāng)庫(kù)的域名;
          • REGISTRY_USER 設(shè)置為本地鏡像倉(cāng)庫(kù)的用戶(hù)名;
          • REGISTRY_PASSWORD 設(shè)置為本地鏡像倉(cāng)庫(kù)的密碼。
          在看點(diǎn)一下
          瀏覽 87
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  操碰在线视频 | 国产一区二区毛片 | 日本欧美国产 | 暴操美女视频网站 | 国产女人18毛片18精品 |