1. 程式人生 > 實用技巧 >Docker 系列(六):公有倉庫與私有倉庫

Docker 系列(六):公有倉庫與私有倉庫

Docker Hub

目前 Docker 官方維護了一個公共倉庫Docker Hub,其中已經包括了數量超過2,650,000的映象。大部分需求都可以通過在 Docker Hub 中直接下載映象來實現。

註冊

你可以在https://hub.docker.com免費註冊一個 Docker 賬號。

登入

可以通過執行docker login命令互動式的輸入使用者名稱及密碼來完成在命令列介面登入 Docker Hub。

你可以通過docker logout退出登入。

拉取映象

你可以通過docker search命令來查詢官方倉庫中的映象,並利用docker pull命令來將它下載到本地。

例如以centos

為關鍵詞進行搜尋:

$ docker search centos
NAME                                            DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
centos                                          The official build of CentOS.                   465       [OK]
tianon/centos                                   CentOS 5 and 6, created using rinse instea...   28
blalor/centos                                   Bare-bones base CentOS 6.5 image                6                    [OK]
saltstack/centos-6-minimal                                                                      6                    [OK]
tutum/centos-6.4                                DEPRECATED. Use tutum/centos:6.4 instead. ...   5                    [OK]

可以看到返回了很多包含關鍵字的映象,其中包括映象名字、描述、收藏數(表示該映象的受關注程度)、是否官方建立(OFFICIAL)、是否自動構建 (AUTOMATED)。

根據是否是官方提供,可將映象分為兩類。

一種是類似centos這樣的映象,被稱為基礎映象或根映象。這些基礎映象由 Docker 公司建立、驗證、支援、提供。這樣的映象往往使用單個單詞作為名字。

還有一種型別,比如tianon/centos映象,它是由 Docker Hub 的註冊使用者建立並維護的,往往帶有使用者名稱稱字首。可以通過字首username/來指定使用某個使用者提供的映象,比如 tianon 使用者。

另外,在查詢的時候通過--filter=stars=N

引數可以指定僅顯示收藏數量為N以上的映象。

下載官方centos映象到本地。

$ docker pull centos
Pulling repository centos
0b443ba03958: Download complete
539c0211cd76: Download complete
511136ea3c5a: Download complete
7064731afe90: Download complete

推送映象

使用者也可以在登入後通過docker push命令來將自己的映象推送到 Docker Hub。

以下命令中的username請替換為你的 Docker 賬號使用者名稱。

$ docker tag ubuntu:18.04 username/ubuntu:18.04

$ docker image ls

REPOSITORY                                               TAG                    IMAGE ID            CREATED             SIZE
ubuntu                                                   18.04                  275d79972a86        6 days ago          94.6MB
username/ubuntu                                          18.04                  275d79972a86        6 days ago          94.6MB

$ docker push username/ubuntu:18.04


私有倉庫

有時候使用 Docker Hub 這樣的公共倉庫可能不方便,使用者可以建立一個本地倉庫供私人使用。

本節介紹如何使用本地倉庫。

docker-registry是官方提供的工具,可以用於構建私有的映象倉庫。本文內容基於docker-registryv2.x 版本。

安裝執行 docker-registry

容器執行

你可以通過獲取官方registry映象來執行。

$ docker run -d -p 5000:5000 --restart=always --name registry registry

這將使用官方的registry映象來啟動私有倉庫。預設情況下,倉庫會被建立在容器的/var/lib/registry目錄下。你可以通過-v引數來將映象檔案存放在本地的指定路徑。例如下面的例子將上傳的映象放到本地的/opt/data/registry目錄。

$ docker run -d \
    -p 5000:5000 \
    -v /opt/data/registry:/var/lib/registry \
    registry

在私有倉庫上傳、搜尋、下載映象

建立好私有倉庫之後,就可以使用docker tag來標記一個映象,然後推送它到倉庫。例如私有倉庫地址為127.0.0.1:5000

先在本機檢視已有的映象。

$ docker image ls
REPOSITORY                        TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu                            latest              ba5877dc9bec        6 weeks ago         192.7 MB

使用docker tagubuntu:latest這個映象標記為127.0.0.1:5000/ubuntu:latest

格式為docker tag IMAGE[:TAG] [REGISTRY_HOST[:REGISTRY_PORT]/]REPOSITORY[:TAG]

$ docker tag ubuntu:latest 127.0.0.1:5000/ubuntu:latest
$ docker image ls
REPOSITORY                        TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu                            latest              ba5877dc9bec        6 weeks ago         192.7 MB
127.0.0.1:5000/ubuntu:latest      latest              ba5877dc9bec        6 weeks ago         192.7 MB

使用docker push上傳標記的映象。

$ docker push 127.0.0.1:5000/ubuntu:latest
The push refers to repository [127.0.0.1:5000/ubuntu]
373a30c24545: Pushed
a9148f5200b0: Pushed
cdd3de0940ab: Pushed
fc56279bbb33: Pushed
b38367233d37: Pushed
2aebd096e0e2: Pushed
latest: digest: sha256:fe4277621f10b5026266932ddf760f5a756d2facd505a94d2da12f4f52f71f5a size: 1568

curl檢視倉庫中的映象。

$ curl 127.0.0.1:5000/v2/_catalog
{"repositories":["ubuntu"]}

這裡可以看到{"repositories":["ubuntu"]},表明映象已經被成功上傳了。

先刪除已有映象,再嘗試從私有倉庫中下載這個映象。

$ docker image rm 127.0.0.1:5000/ubuntu:latest

$ docker pull 127.0.0.1:5000/ubuntu:latest
Pulling repository 127.0.0.1:5000/ubuntu:latest
ba5877dc9bec: Download complete
511136ea3c5a: Download complete
9bad880da3d2: Download complete
25f11f5fb0cb: Download complete
ebc34468f71d: Download complete
2318d26665ef: Download complete

$ docker image ls
REPOSITORY                         TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
127.0.0.1:5000/ubuntu:latest       latest              ba5877dc9bec        6 weeks ago         192.7 MB

注意事項

如果你不想使用127.0.0.1:5000作為倉庫地址,比如想讓本網段的其他主機也能把映象推送到私有倉庫。你就得把例如192.168.199.100:5000這樣的內網地址作為私有倉庫地址,這時你會發現無法成功推送映象。

這是因為 Docker 預設不允許非HTTPS方式推送映象。我們可以通過 Docker 的配置選項來取消這個限制,或者檢視下一節配置能夠通過HTTPS訪問的私有倉庫。

Ubuntu 16.04+, Debian 8+, centos 7

對於使用systemd的系統,請在/etc/docker/daemon.json中寫入如下內容(如果檔案不存在請新建該檔案)

{
  "registry-mirror": [
    "https://dockerhub.azk8s.cn"
  ],
  "insecure-registries": [
    "192.168.199.100:5000"
  ]
}

注意:該檔案必須符合json規範,否則 Docker 將不能啟動。

其他

對於 Docker Desktop for Windows 、 Docker Desktop for Mac 在設定中的Docker Engine中進行編輯 ,增加和上邊一樣的字串即可。

私有倉庫高階配置

上一節我們搭建了一個具有基礎功能的私有倉庫,本小節我們來使用Docker Compose搭建一個擁有許可權認證、TLS 的私有倉庫。

新建一個資料夾,以下步驟均在該資料夾中進行。

準備站點證書

如果你擁有一個域名,國內各大雲服務商均提供免費的站點證書。你也可以使用openssl自行簽發證書。

這裡假設我們將要搭建的私有倉庫地址為docker.domain.com,下面我們介紹使用openssl自行簽發docker.domain.com的站點 SSL 證書。

第一步建立CA私鑰。

$ openssl genrsa -out "root-ca.key" 4096

第二步利用私鑰建立CA根證書請求檔案。

$ openssl req \
          -new -key "root-ca.key" \
          -out "root-ca.csr" -sha256 \
          -subj '/C=CN/ST=Shanxi/L=Datong/O=Your Company Name/CN=Your Company Name Docker Registry CA'

以上命令中-subj引數裡的/C表示國家,如CN/ST表示省;/L表示城市或者地區;/O表示組織名;/CN通用名稱。

第三步配置CA根證書,新建root-ca.cnf

[root_ca]
basicConstraints = critical,CA:TRUE,pathlen:1
keyUsage = critical, nonRepudiation, cRLSign, keyCertSign
subjectKeyIdentifier=hash

第四步簽發根證書。

$ openssl x509 -req  -days 3650  -in "root-ca.csr" \
               -signkey "root-ca.key" -sha256 -out "root-ca.crt" \
               -extfile "root-ca.cnf" -extensions \
               root_ca

第五步生成站點SSL私鑰。

$ openssl genrsa -out "docker.domain.com.key" 4096

第六步使用私鑰生成證書請求檔案。

$ openssl req -new -key "docker.domain.com.key" -out "site.csr" -sha256 \
          -subj '/C=CN/ST=Shanxi/L=Datong/O=Your Company Name/CN=docker.domain.com'

第七步配置證書,新建site.cnf檔案。

[server]
authorityKeyIdentifier=keyid,issuer
basicConstraints = critical,CA:FALSE
extendedKeyUsage=serverAuth
keyUsage = critical, digitalSignature, keyEncipherment
subjectAltName = DNS:docker.domain.com, IP:127.0.0.1
subjectKeyIdentifier=hash

第八步簽署站點SSL證書。

$ openssl x509 -req -days 750 -in "site.csr" -sha256 \
    -CA "root-ca.crt" -CAkey "root-ca.key"  -CAcreateserial \
    -out "docker.domain.com.crt" -extfile "site.cnf" -extensions server

這樣已經擁有了docker.domain.com的網站 SSL 私鑰docker.domain.com.key和 SSL 證書docker.domain.com.crt及 CA 根證書root-ca.crt

新建ssl資料夾並將docker.domain.com.keydocker.domain.com.crtroot-ca.crt這三個檔案移入,刪除其他檔案。

配置私有倉庫

私有倉庫預設的配置檔案位於/etc/docker/registry/config.yml,我們先在本地編輯config.yml,之後掛載到容器中。

version: 0.1
log:
  accesslog:
    disabled: true
  level: debug
  formatter: text
  fields:
    service: registry
    environment: staging
storage:
  delete:
    enabled: true
  cache:
    blobdescriptor: inmemory
  filesystem:
    rootdirectory: /var/lib/registry
auth:
  htpasswd:
    realm: basic-realm
    path: /etc/docker/registry/auth/nginx.htpasswd
http:
  addr: :443
  host: https://docker.domain.com
  headers:
    X-Content-Type-Options: [nosniff]
  http2:
    disabled: false
  tls:
    certificate: /etc/docker/registry/ssl/docker.domain.com.crt
    key: /etc/docker/registry/ssl/docker.domain.com.key
health:
  storagedriver:
    enabled: true
    interval: 10s
threshold: 3

生成 http 認證檔案

$ mkdir auth

$ docker run --rm \
    --entrypoint htpasswd \
    registry \
    -Bbn username password > auth/nginx.htpasswd

將上面的usernamepassword替換為你自己的使用者名稱和密碼。

編輯docker-compose.yml

version: '3'

services:
  registry:
    image: registry
    ports:
      - "443:443"
    volumes:
      - ./:/etc/docker/registry
      - registry-data:/var/lib/registry

volumes:
  registry-data:

修改 hosts

編輯/etc/hosts

127.0.0.1 docker.domain.com

啟動

$ docker-compose up -d

這樣我們就搭建好了一個具有許可權認證、TLS 的私有倉庫,接下來我們測試其功能是否正常。

測試私有倉庫功能

由於自行簽發的 CA 根證書不被系統信任,所以我們需要將 CA 根證書ssl/root-ca.crt移入/etc/docker/certs.d/docker.domain.com資料夾中。

$ sudo mkdir -p /etc/docker/certs.d/docker.domain.com

$ sudo cp ssl/root-ca.crt /etc/docker/certs.d/docker.domain.com/ca.crt

登入到私有倉庫。

$ docker login docker.domain.com

嘗試推送、拉取映象。

$ docker pull ubuntu:18.04

$ docker tag ubuntu:18.04 docker.domain.com/username/ubuntu:18.04

$ docker push docker.domain.com/username/ubuntu:18.04

$ docker image rm docker.domain.com/username/ubuntu:18.04

$ docker pull docker.domain.com/username/ubuntu:18.04

如果我們退出登入,嘗試推送映象。

$ docker logout docker.domain.com

$ docker push docker.domain.com/username/ubuntu:18.04

no basic auth credentials

發現會提示沒有登入,不能將映象推送到私有倉庫中。

注意事項

如果你本機佔用了443埠,你可以配置Nginx 代理,這裡不再贅述。

Nexus3.x 的私有倉庫

使用 Docker 官方的 Registry 建立的倉庫面臨一些維護問題。比如某些映象刪除以後空間預設是不會回收的,需要一些命令去回收空間然後重啟 Registry 程式。在企業中把內部的一些工具包放入 Nexus 中是比較常見的做法,最新版本Nexus3.x全面支援 Docker 的私有映象。所以使用Nexus3.x一個軟體來管理Docker,Maven,Yum,PyPI等是一個明智的選擇。

啟動 Nexus 容器

$ docker run -d --name nexus3 --restart=always \
    -p 8081:8081 \
    --mount src=nexus-data,target=/nexus-data \
    sonatype/nexus3

等待 3-5 分鐘,如果nexus3容器沒有異常退出,那麼你可以使用瀏覽器開啟http://YourIP:8081訪問 Nexus 了。

第一次啟動 Nexus 的預設帳號是admin密碼是admin123登入以後點選頁面上方的齒輪按鈕進行設定。

建立倉庫

建立一個私有倉庫的方法:Repository->Repositories點選右邊選單Create repository選擇docker (hosted)

  • Name: 倉庫的名稱
  • HTTP: 倉庫單獨的訪問埠
  • Enable Docker V1 API: 如果需要同時支援 V1 版本請勾選此項(不建議勾選)。
  • Hosted -> Deployment pollcy: 請選擇 Allow redeploy 否則無法上傳 Docker 映象。

其它的倉庫建立方法請各位自己摸索,還可以建立一個 docker (proxy) 型別的倉庫連結到 DockerHub 上。再建立一個 docker (group) 型別的倉庫把剛才的 hosted 與 proxy 新增在一起。主機在訪問的時候預設下載私有倉庫中的映象,如果沒有將連結到 DockerHub 中下載並快取到 Nexus 中。

新增訪問許可權

選單Security->Realms把 Docker Bearer Token Realm 移到右邊的框中儲存。

新增使用者規則:選單Security->Roles->Create rolePrivlleges選項搜尋 docker 把相應的規則移動到右邊的框中然後儲存。

新增使用者:選單Security->Users->Create local userRoles選項中選中剛才建立的規則移動到右邊的視窗儲存。

NGINX 加密代理

證書的生成請參見私有倉庫高階配置裡面證書生成一節。

NGINX 示例配置如下

upstream register
{
    server "YourHostName OR IP":5001; #埠為上面新增的私有映象倉庫是設定的 HTTP 選項的埠號
    check interval=3000 rise=2 fall=10 timeout=1000 type=http;
    check_http_send "HEAD / HTTP/1.0\r\n\r\n";
    check_http_expect_alive http_4xx;
}

server {
    server_name YourDomainName;#如果沒有 DNS 伺服器做解析,請刪除此選項使用本機 IP 地址訪問
    listen       443 ssl;

    ssl_certificate key/example.crt;
    ssl_certificate_key key/example.key;

    ssl_session_timeout  5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers  HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers   on;
    large_client_header_buffers 4 32k;
    client_max_body_size 300m;
    client_body_buffer_size 512k;
    proxy_connect_timeout 600;
    proxy_read_timeout   600;
    proxy_send_timeout   600;
    proxy_buffer_size    128k;
    proxy_buffers       4 64k;
    proxy_busy_buffers_size 128k;
    proxy_temp_file_write_size 512k;

    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Port $server_port;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://register;
        proxy_read_timeout 900s;
    }
    error_page   500 502 503 504  /50x.html;
}
原文整理:https://docker_practice.gitee.io/zh-cn/repository/