如何讓Docker鏡像飛起來

  • 2020 年 3 月 31 日
  • 筆記

前言

Docker用起來非常爽,尤其是用於DevOps實踐時。但是,當你在國內或者本地拉取鏡像時,經常會碰到各種“便秘”——要麼鏡像拉取緩慢,要麼時斷時連,要麼連接超時!

便秘

當我們的鏡像又比較大時(比如某人在代碼裏面丟了個魔獸爭霸的包),這簡直是一個噩夢!那麼如何解決這個問題?接下來我們就主要從以下幾個方面來解決這個問題:

  • 使用鏡像加速器
  • 換源
  • 自己做鏡像推送到國內倉庫
  • 自己搭建就近鏡像倉庫
  • 最後的絕招(保密)

img

鏡像加速器

玩網遊卡都可以祭出加速器,鏡像拉取通用有相關的加速器。國內的雲廠商基本上都提供了鏡像加速器:

Docker Hub 鏡像加速器列表

鏡像加速器 鏡像加速器地址 專屬加速器 其它加速
Docker 中國官方鏡像 https://registry.docker-cn.com   Docker Hub
DaoCloud 鏡像站 http://f1361db2.m.daocloud.io 可登錄,系統分配 Docker Hub
Azure 中國鏡像 https://dockerhub.azk8s.cn   Docker Hub、GCR、Quay
科大鏡像站 https://docker.mirrors.ustc.edu.cn   Docker Hub、GCRQuay
阿里雲 https://.mirror.aliyuncs.com 需登錄,系統分配 Docker Hub
七牛雲 https://reg-mirror.qiniu.com   Docker Hub、GCR、Quay
網易雲 https://hub-mirror.c.163.com   Docker Hub
騰訊雲 https://mirror.ccs.tencentyun.com   Docker Hub

如何使用鏡像加速器呢?

Docker Hub 鏡像加速器配置

Linux系統可以執行以下Shell:

sh

配置了之後,可以通過“docker info”命令來查看是否生效:
docker info

如果是Windows 10呢?可以在如下圖所示的界面處配置:

Windows 10配置

換源

加速器用起來非常爽,但是很多時候某些鏡像就算是配置了加速器也不好使(可能和加速器的國際帶寬有關係),這個時候就必須換源了。畢竟加速器不是萬能的,尤其是當你的鏡像比較大的時候。這時候你就要找合適的源了。

比如.NET Core 的SDK鏡像,我們可以統一使用Azure中國的鏡像源,如下表所示,我們看到“mcr.microsoft.com”在國內對應的代理為“mcr.azk8s.cn”:

global proxy in China format example
dockerhub (docker.io) dockerhub.azk8s.cn dockerhub.azk8s.cn//: dockerhub.azk8s.cn/microsoft/azure-cli:2.0.61 dockerhub.azk8s.cn/library/nginx:1.15
gcr.io gcr.azk8s.cn gcr.azk8s.cn//: gcr.azk8s.cn/google_containers/hyperkube-amd64:v1.13.5
quay.io quay.azk8s.cn quay.azk8s.cn//: quay.azk8s.cn/deis/go-dev:v1.10.0
mcr.microsoft.com mcr.azk8s.cn mcr.azk8s.cn//: mcr.azk8s.cn/oss/kubernetes/hyperkube:v1.15.7

因此,我們可以使用“mcr.azk8s.cn”來替代官方提供的“mcr.microsoft.com”源:

# docker pull  mcr.microsoft.com/dotnet/core/sdk:2.2-stretch  docker pull mcr.azk8s.cn/dotnet/core/sdk:2.2-stretch

如上述代碼所示,我們將Azure國際的源換成了Azure中國的源,拉包速度就會飛快。換源了,意味着我們也需要將Dockerfile的命令也進行修改:

#FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build  #修改為Azure中國鏡像  FROM mcr.azk8s.cn/dotnet/core/sdk:2.2-stretch AS build

自己做鏡像推送到國內倉庫

有源的還還說,要是沒源怎麼辦?那總不能涼拌吧?那就自己做吧。可以基於GitHub託管,Azure DevOps和Docker hub進行海外構建,然後將鏡像推送到國內的鏡像倉庫之中。如下面這個開源庫,用於構建項目中使用的aspnetcore的運行時公共基礎鏡像,同時提供了騰訊雲公共鏡像和Docker Hub公共鏡像以供國內外使用:
https://github.com/xin-lai/aspnetcore-docker

相關鏡像標籤說明

標籤名稱 說明
latest 最新鏡像,當前為3.1
2.2 Asp.Net Core Runtime 2.2
2.2withfonts Asp.Net Core Runtime 2.2 (包含字體)
3.0 Asp.Net Core Runtime 3.0
3.1 Asp.Net Core Runtime 3.1

然後,僅需在Dockerfile中替換為自己的源即可,即可享受快的飛起:

#說明見:https://github.com/xin-lai/aspnetcore-docker  FROM ccr.ccs.tencentyun.com/magicodes/aspnetcore-runtime:2.2withfonts AS base

這裡分享一個技巧:Linux下使用apt裝包很多時候非常緩慢而且不靠譜,有時候換成國內的代理也很不靠譜,這時候可以考慮使用海外構建,做成鏡像。

自己搭建就近鏡像倉庫

服務器帶寬不行,本地網絡不佳,怎麼辦?還能怎麼辦,自己搭建倉庫吧。這裡推薦使用nexus,nexus可以託管各種包,包括Docker、Nuget、Jar、npm、Bower等等包,簡直不要太犀利了。如何搭建?Yaml常考如下:

apiVersion: apps/v1beta2  kind: Deployment  metadata:    labels:      k8s-app: nexus    name: nexus    namespace: default  spec:    progressDeadlineSeconds: 600    replicas: 1    revisionHistoryLimit: 10    selector:      matchLabels:        k8s-app: nexus    strategy:      type: Recreate    template:      metadata:        labels:          k8s-app: nexus      spec:        containers:        - image: sonatype/nexus3          imagePullPolicy: IfNotPresent          name: nexus          resources:            limits:              cpu: "2"              memory: 5024Mi            requests:              cpu: 10m              memory: 256Mi          volumeMounts:          - mountPath: /nexus-data            name: data        restartPolicy: Always        nodeName: k8s-node1 #強制約束將Pod調度到指定的Node節點上        terminationGracePeriodSeconds: 30 #Pod結束時等待時長(單位為秒)        volumes:          - name: data            hostPath:   #使用主機目錄              path: /var/nexus        hostNetwork: true  ---  apiVersion: v1  kind: Service  metadata:    name: nexus    namespace: default  spec:    ports:    - name: tcp-8081-8081      nodePort: 30081      port: 8081      protocol: TCP      targetPort: 8081    - name: tcp-8082-8082      nodePort: 30082      port: 8082      protocol: TCP      targetPort: 8082    - name: tcp-8083-8083      nodePort: 30083      port: 8083      protocol: TCP      targetPort: 8083    - name: tcp-8084-8084      nodePort: 30084      port: 8084      protocol: TCP      targetPort: 8084    - name: tcp-8085-8085      nodePort: 30085      port: 8085      protocol: TCP      targetPort: 8085    - name: tcp-8086-8086      nodePort: 30086      port: 8086      protocol: TCP      targetPort: 8086    selector:      k8s-app: nexus    sessionAffinity: None    type: NodePort

最後的絕招

還不行,用U盤複製吧。別說認識我。你不信可以通過U盤複製?可以去了解下以下兩個命令:

  • docker save
  • docker load

U盤