1. 程式人生 > >Docker 映象加速教程

Docker 映象加速教程

> 原文連結:[https://fuckcloudnative.io/posts/docker-registry-proxy/](https://fuckcloudnative.io/posts/docker-registry-proxy/) 在使用 Docker 和 Kubernetes 時,我們經常需要訪問 `gcr.io` 和 `quay.io` 映象倉庫,由於眾所周知的原因,這些映象倉庫在中國都無法訪問,唯一能訪問的是 Docker Hub,但速度也是奇慢無比。`gcr.azk8s.cn` 是 `gcr.io` 映象倉庫的代理站點,原來可以通過 `gcr.azk8s.cn` 訪問 gcr.io 倉庫裡的映象,但是目前 `*.azk8s.cn` 已經僅限於 `Azure` 中國的 IP 使用,不再對外提供服務了。國內其他的映象加速方案大多都是採用定時同步的方式來快取,這種方法是有一定延遲的,不能保證及時更新,ustc 和七牛雲等映象加速器我都試過了,非常不靠譜,很多映象都沒有。 為了能夠順利訪問 `gcr.io` 等映象倉庫,我們需要在牆外自己搭建一個類似於 `gcr.azk8s.cn` 的映象倉庫代理站點。利用 Docker 的開源專案 [registry](https://docs.docker.com/registry/) 就可以實現這個需求,registry 不僅可以作為本地私有映象倉庫,還可以作為上游映象倉庫的快取,也就是 `pull through cache`。 先來感受下速度: ![](https://img2020.cnblogs.com/other/1737323/202102/1737323-20210226113336007-1953466932.png) ![](https://img2020.cnblogs.com/other/1737323/202102/1737323-20210226113336333-128206995.png) ![](https://img2020.cnblogs.com/other/1737323/202102/1737323-20210226113336584-1917842955.jpg) ![](https://img2020.cnblogs.com/other/1737323/202102/1737323-20210226113336796-1931131649.jpg) ## 1. 前提條件 ---- + 一臺能夠施展魔法的伺服器(你懂得,可以直接訪問 gcr.io) + 一個域名和域名相關的 SSL 證書(docker pull 映象時需要驗證域名證書),一般用 [Let's Encrypt](https://letsencrypt.org/) 就夠了。 ## 2. 核心思路 ---- registry 可以通過設定引數 `remoteurl` 將其作為遠端倉庫的快取倉庫,這樣當你通過這個私有倉庫的地址拉取映象時,regiistry 會先將映象快取到本地儲存,然後再提供給拉取的客戶端(有可能這兩個步驟是同時的,我也不太清楚)。我們可以先部署一個私有 registry,然後將 `remoteurl` 設為需要加速的映象倉庫地址,基本上就可以了。 ## 3. 定製 registry 為了能夠支援快取 `docker.io`、`gcr.io`、`k8s.gcr.io`、`quay.io` 和 `ghcr.io` 等常見的公共映象倉庫,我們需要對 registry 的配置檔案進行定製,Dockerfile 如下: ```dockerfile FROM registry:2.6 LABEL maintainer="registry-proxy Docker Maintainers https://fuckcloudnative.io" ENV PROXY_REMOTE_URL="" \ DELETE_ENABLED="" COPY entrypoint.sh /entrypoint.sh ``` 其中 `entrypoint.sh` 用來將環境變數傳入配置檔案: {{< expand "entrypoint.sh" >}} ```bash #!/bin/sh set -e CONFIG_YML=/etc/docker/registry/config.yml if [ -n "$PROXY_REMOTE_URL" -a `grep -c "$PROXY_REMOTE_URL" $CONFIG_YML` -eq 0 ]; then echo "proxy:" >> $CONFIG_YML echo " remoteurl: $PROXY_REMOTE_URL" >> $CONFIG_YML echo " username: $PROXY_USERNAME" >> $CONFIG_YML echo " password: $PROXY_PASSWORD" >> $CONFIG_YML echo "------ Enabled proxy to remote: $PROXY_REMOTE_URL ------" elif [ $DELETE_ENABLED = true -a `grep -c "delete:" $CONFIG_YML` -eq 0 ]; then sed -i '/rootdirectory/a\ delete:' $CONFIG_YML sed -i '/delete/a\ enabled: true' $CONFIG_YML echo "------ Enabled local storage delete -----" fi sed -i "/headers/a\ Access-Control-Allow-Origin: ['*']" $CONFIG_YML sed -i "/headers/a\ Access-Control-Allow-Methods: ['HEAD', 'GET', 'OPTIONS', 'DELETE']" $CONFIG_YML sed -i "/headers/a\ Access-Control-Expose-Headers: ['Docker-Content-Digest']" $CONFIG_YML case "$1" in *.yaml|*.yml) set -- registry serve "$@" ;; serve|garbage-collect|help|-*) set -- registry "$@" ;; esac exec "$@" ``` {{< /expand >
}} ## 4. 啟動快取服務 構建好 Docker 映象之後,就可以啟動服務了。如果你不想自己構建,可以直接用我的映象:`yangchuansheng/registry-proxy`。 一般來說,即使你要同時快取 `docker.io`、`gcr.io`、`k8s.gcr.io`、`quay.io` 和 `ghcr.io`,一臺 `1C 2G` 的雲主機也足夠了(前提是你不在上面跑其他的服務)。我的部落格、評論服務和其他一堆亂七八糟的服務都要跑在雲主機上,所以一臺是不滿足我的需求的,我直接買了兩臺騰訊雲香港輕量級伺服器。 ![](https://img2020.cnblogs.com/other/1737323/202102/1737323-20210226113337036-1470446188.png) 既然買了兩臺,肯定得[組個 k3s 叢集](https://fuckcloudnative.io/posts/deploy-k3s-cross-public-cloud/)啦,看主機名就知道我是用來幹啥的。其中 2C 4G 作為 master 節點,1C 2G 作為 node 節點。 以 `docker.io` 為例,建立資源清單: {{< expand "dockerhub.yaml" >}} ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: dockerhub labels: app: dockerhub spec: replicas: 1 selector: matchLabels: app: dockerhub template: metadata: labels: app: dockerhub spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - dockerhub topologyKey: kubernetes.io/hostname weight: 1 dnsPolicy: None dnsConfig: nameservers: - 8.8.8.8 - 8.8.4.4 containers: - name: dockerhub image: yangchuansheng/registry-proxy:latest env: - name: PROXY_REMOTE_URL value: https://registry-1.docker.io - name: PROXY_USERNAME value: yangchuansheng - name: PROXY_PASSWORD value: ******** ports: - containerPort: 5000 protocol: TCP volumeMounts: - mountPath: /etc/localtime name: localtime - mountPath: /var/lib/registry name: registry volumes: - name: localtime hostPath: path: /etc/localtime - name: registry hostPath: path: /var/lib/registry --- apiVersion: v1 kind: Service metadata: name: dockerhub labels: app: dockerhub spec: selector: app: dockerhub ports: - protocol: TCP name: http port: 5000 targetPort: 5000 ``` {{< /expand >
}} 使用資源清單建立對應的服務: ```bash