Docker私有倉庫搭建

2022-08-12 06:05:51

Docker私有倉庫搭建

1、Docker Registry

網上有很多的Registry伺服器都支援第三方使用者註冊,而後基於使用者名稱去做自己的倉庫,但是使用網際網路上的Registry有一個缺陷,那就是我們去推播和下載映象時都不會很快,而在生產環境中很可能並行啟動的容器將達到幾十、上百個,而且很有可能每個伺服器本地是沒有映象的,此時如果通過網際網路去下載映象會有很多問題,比如下載速度會很慢、頻寬會用很多等等,如果頻寬不夠的話,下載至啟動這個過程可能要持續個幾十分鐘,這已然違背了使用容器會更加輕量、快速的初衷和目的。因此,很多時候我們很有可能需要去做自己的私有Registry

Registry用於儲存docker映象,包括映象的層次結構和後設資料。使用者可以自建Registry,也可以使用官方的Docker Hub

Docker Registry分類:

  • Sponsor Registry:第三方的Registry,供客戶和Docker社群使用
  • Mirror Registry:第三方的Registry,只讓客戶使用
  • Vendor Registry:由釋出docker映象的供應商提供的registry
  • Private Registry:通過設有防火牆和額外的安全層的私有實體提供的registry

事實上,如果運維的系統環境託管在雲端計算服務上,比如阿里雲,那麼用阿里雲的Registry則是最好的選擇。很多時候我們的生產環境不會在本地,而是託管在資料中心機房裡,如果我們在資料中心機房裡的某臺主機上部署Registry,因為都在同一機房,所以屬於同一區域網,此時資料傳輸走內網,效率會極大的提升。

所有的Registry預設情況下都是基於https工作的,這是Docker的基本要求,而我自建Registry時很可能是基於http工作的,但是Docker預設是拒絕使用http提供Registry服務的,除非明確的告訴它,我們就是要用http協定的Registry

2、Docker Private Registry

為了幫助我們快速建立私有Registry,Docker專門提供了一個名為Docker Distribution的軟體包,我們可以通過安裝這個軟體包快速構建私有倉庫。

既然Docker是為了執行程式的,Docker Distribution能否執行在容器中?

容器時代,任何程式都應該執行在容器中,除了Kernel和init。而為了能夠做Docker Private Registry,Docker Hub官方直接把Registry做成了映象,我們可以直接將其pull到本地並啟動為容器即可快速實現私有Registry

Registry的主要作用是託管映象,Registry執行在容器中,而容器自己的檔案系統是隨著容器的生命週期終止和刪除而被刪除的,所以當我們把Registry執行在容器中時,使用者端上傳了很多映象,隨著Registry容器的終止並刪除,所有映象都將化為烏有,因此這些映象應該放在儲存捲上,而且這個儲存卷最好不要放在Docker主機本地,而應該放在一個網路共用儲存上,比如NFS。不過,映象檔案自己定義的儲存卷,還是一個放在Docker本地、Docker管理的卷,我們可以手動的將其改成使用其它檔案系統的儲存卷。

這就是使用容器來執行Registry的一種簡單方式。自建Registry的另一種方式,就是直接安裝docker-distribution軟體。

2.1 使用docker-distribution自建Registry

環境:

角色 主機名 IP
docker node1 192.168.111.135
registry node2 192.168.111.138

在node2上安裝docker-distribution

[root@node2 ~]# yum -y install http://mirror.centos.org/centos/7/extras/x86_64/Packages/docker-distribution-2.6.2-2.git48294d9.el7.x86_64.rpm
[root@node2 ~]# cd /etc/docker-distribution/registry/
[root@node2 registry]# ls
config.yml
[root@node2 registry]# vim config.yml 
version: 0.1
log:
  fields:
    service: registry
storage:
    cache:
        layerinfo: inmemory
    filesystem:		
        rootdirectory: /var/lib/registry		# 修改此處為一個容量大的磁碟分割區目錄
http:
    addr: :5000

[root@node2 ~]# systemctl start docker-distribution.service 
[root@node2 ~]# ss -anlt
State     Recv-Q    Send-Q         Local Address:Port         Peer Address:Port    Process    
LISTEN    0         128                  0.0.0.0:22                0.0.0.0:*                  
LISTEN    0         128                     [::]:22                   [::]:*                  
LISTEN    0         128                        *:5000                    *:*                  

在node1上使用自建的Registry去上傳映象

# 使用insecure-registries引數新增http支援
[root@node2 ~]# vim /etc/docker/daemon.json
{
  "registry-mirrors": ["https://6vrrj6n2.mirror.aliyuncs.com"],
  "insecure-registries": ["192.168.111.138:5000"]
}
[root@node1 ~]# systemctl restart docker
[root@node1 ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
busybox      latest    beae173ccac6   7 months ago   1.24MB
[root@node1 ~]# docker tag busybox:latest 192.168.111.138:5000/busybox:v1
[root@node1 ~]# docker images
REPOSITORY                     TAG       IMAGE ID       CREATED        SIZE
192.168.111.138:5000/busybox   v1        beae173ccac6   7 months ago   1.24MB
busybox                        latest    beae173ccac6   7 months ago   1.24MB
[root@node1 ~]# docker push 192.168.111.138:5000/busybox:v1
The push refers to repository [192.168.111.138:5000/busybox]
01fd6df81c8e: Layer already exists 
v1: digest: sha256:62ffc2ed7554e4c6d360bce40bbcf196573dd27c4ce080641a2c59867e732dee size: 527

在node2上拉取node1自建的Registry上的映象

[root@node2 ~]# docker images
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE
[root@node2 ~]# docker pull 192.168.111.138:5000/busybox:v1
v1: Pulling from busybox
5cc84ad355aa: Pull complete 
Digest: sha256:62ffc2ed7554e4c6d360bce40bbcf196573dd27c4ce080641a2c59867e732dee
Status: Downloaded newer image for 192.168.111.138:5000/busybox:v1
192.168.111.138:5000/busybox:v1
[root@node2 ~]# docker images
REPOSITORY                     TAG       IMAGE ID       CREATED        SIZE
192.168.111.138:5000/busybox   v1        beae173ccac6   7 months ago   1.24MB

# 檢視私有倉庫映象資訊
[root@node2 ~]# curl http://192.168.111.138:5000/v2/_catalog
{"repositories":["busybox"]}

# 檢視私有倉庫映象的tag資訊
[root@node2 ~]# curl http://192.168.111.138:5000/v2/busybox/tags/list
{"name":"busybox","tags":["latest","v1"]}

2.2 使用官方映象自建Registry

# 使用insecure-registries引數新增http支援
[root@node2 ~]# vim /etc/docker/daemon.json
{
  "registry-mirrors": ["https://6vrrj6n2.mirror.aliyuncs.com"],
  "insecure-registries": ["192.168.111.138:5000"]
}
[root@node1 ~]# systemctl restart docker

# 使用registry映象建立容器registry
[root@node2 ~]# docker run -dit --name registry -p 5000:5000 -v /opt/registry:/tmp/registry registry
[root@node2 ~]# docker ps
CONTAINER ID   IMAGE      COMMAND                  CREATED          STATUS          PORTS                                       NAMES
51a839662d15   registry   "/entrypoint.sh /etc…"   34 seconds ago   Up 33 seconds   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   registry
[root@node2 ~]# ss -anlt
State                 Recv-Q                Send-Q                               Local Address:Port                                 Peer Address:Port                Process                
LISTEN                0                     128                                        0.0.0.0:22                                        0.0.0.0:*                                          
LISTEN                0                     128                                        0.0.0.0:5000                                      0.0.0.0:*                                          
LISTEN                0                     128                                           [::]:22                                           [::]:*                                          
LISTEN                0                     128                                           [::]:5000                                         [::]:*   

# 為busybox映象新增別名
[root@node2 ~]# docker tag busybox:latest 192.168.111.138:5000/zhaosl:v1
[root@node2 ~]# docker images
REPOSITORY                     TAG       IMAGE ID       CREATED        SIZE
192.168.111.138:5000/busybox   v1        beae173ccac6   7 months ago   1.24MB
192.168.111.138:5000/zhaosl    v1        beae173ccac6   7 months ago   1.24MB
busybox                        latest    beae173ccac6   7 months ago   1.24MB
registry                       latest    b8604a3fe854   9 months ago   26.2MB

# 把映象推播到私有倉庫
[root@node2 ~]# docker push 192.168.111.138:5000/zhaosl:v1 
The push refers to repository [192.168.111.138:5000/zhaosl]
01fd6df81c8e: Pushed 
v1: digest: sha256:62ffc2ed7554e4c6d360bce40bbcf196573dd27c4ce080641a2c59867e732dee size: 527
[root@node2 ~]# curl http://192.168.111.138:5000/v2/_catalog
{"repositories":["zhaosl"]}
[root@node2 ~]# curl http://192.168.111.138:5000/v2/zhaosl/tags/list
{"name":"zhaosl","tags":["v1"]}

# 從私有倉庫拉取映象
[root@node2 ~]# docker pull 192.168.111.138:5000/zhaosl:v1 

2.3 Harbor

無論是使用Docker-distribution去自建倉庫,還是通過官方映象跑容器的方式去自建倉庫,通過前面的演示我們可以發現其是非常的簡陋的,還不如直接使用官方的Docker Hub去管理映象來得方便,至少官方的Docker Hub能夠通過web介面來管理映象,還能在web介面執行搜尋,還能基於Dockerfile利用Webhooks和Automated Builds實現自動構建映象的功能,使用者不需要在本地執行docker build,而是把所有build上下文的檔案作為一個倉庫推播到github上,讓Docker Hub可以從github上去pull這些檔案來完成自動構建。

但無論官方的Docker Hub有多強大,它畢竟是在國外,所以速度是最大的瓶頸,我們很多時候是不可能去考慮使用官方的倉庫的,但是上面說的兩種自建倉庫方式又十分簡陋,不便管理,所以後來就出現了一個被 CNCF 組織青睞的專案,其名為Harbor。

2.3.1 Harbor簡介

Harbor是由VMWare在Docker Registry的基礎之上進行了二次封裝,加進去了很多額外程式,而且提供了一個非常漂亮的web介面。

Project Harbor 是一個開源的可信雲原生登入檔專案,用於儲存、簽名和掃描上下文。

Harbor 通過新增使用者通常需要的功能(如安全性、身份和管理)來擴充套件開源 Docker 分發版。

Harbor 支援高階功能,例如使用者管理、存取控制、活動監控和範例間複製。

2.3.2 Harbor的功能

Feathers:

  • 多租戶內容簽名和驗證
  • 安全性和漏洞分析
  • 審計紀錄檔記錄
  • 身份整合和角色存取控制
  • 範例間的映象複製s
  • 可延伸的API和圖形介面
  • 國際化(目前為英文和中文)
2.3.3 Docker compose

Harbor在物理機上部署是非常難的,而為了簡化Harbor的應用,Harbor官方直接把Harbor做成了在容器中執行的應用,而且這個容器在Harbor中依賴類似redis、mysql、pgsql等很多儲存系統,所以它需要編排很多容器協同起來工作,因此VMWare Harbor在部署和使用時,需要藉助於Docker的單機編排工具(Docker compose)來實現。

Compose是一個用於定義和執行多容器Docker應用程式的工具。使用Compose,您可以使用YAML檔案來設定應用程式的服務。然後,只需要一個命令,就可以從設定中建立並啟動所有服務。

Docker Compose官方檔案

2.3.4 Harbor部署

Harbor標準安裝過程包括以下階段:

  1. 確保您的目標主機滿足安裝先決條件 Harbor Installer Precondition
  2. 下載並安裝Harbor Download the Harbor Installer
  3. 設定HTTPS存取埠 Configure HTTPS Access to Harbor
  4. 設定Harbor YML檔案 Configure the Harbor YML File
  5. 設定啟用內部TLS Configure Enabling Internal TLS
  6. 執行安裝程式指令碼 Run the Installer Script

如果安裝失敗,請參見 Harbor安裝故障處理

準備工作

搭建私有倉庫需要的軟體:

軟體 版本 說明
Docker Version 17.06.0-ce+ 或更高 有關安裝說明,請參閱 Docker Engine documentation
Docker Compose Version 1.18.0 或更高 有關安裝說明,請參閱 Docker Compose documentation
Openssl 最好是最新的 用於為埠生成證書和金鑰

Docker安裝:

# 1.首先設定yum倉庫
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-vault-8.5.2111.repo
sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo

# 2.設定映象的倉庫
wget  https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 

# 3.安裝容器相關的。docker-ce(社群版)docker-ee(企業版)
yum install docker-ce 

# 4.啟動docker服務並設定開機自啟
systemctl start docker
systemctl enable docker

Docker Compose安裝:

# 下載docker-compose
[root@node2 bin]# curl -SL https://github.com/docker/compose/releases/download/v2.7.0/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
[root@node2 ~]# cd /usr/local/bin/
[root@node2 bin]# ll
total 25188
-rw-r--r--. 1 root root 25792512 Aug 11 18:49 docker-compose

# 給docker-compose執行許可權
[root@node2 ~]# chmod +x /usr/local/bin/docker-compose 
[root@node2 ~]# ll /usr/local/bin/
total 25188
-rwxr-xr-x. 1 root root 25792512 Aug 11 18:49 docker-compose

Openssl安裝:

# 安裝openssl
[root@node2 ~]# yum -y install openssl
[root@node2 ~]# rpm -qa | grep openssl
openssl-1.1.1g-11.el8.x86_64
openssl-pkcs11-0.4.10-2.el8.x86_64
openssl-libs-1.1.1g-11.el8.x86_64
xmlsec1-openssl-1.2.25-4.el8.x86_64

Harbox快速安裝:

# 下載harbor安裝包
[root@node2 ~]# wget https://github.com/goharbor/harbor/releases/download/v2.4.3/harbor-offline-installer-v2.4.3.tgz
[root@node2 ~]# ls
anaconda-ks.cfg  harbor-offline-installer-v2.4.3.tgz

# 解壓到/usr/local/下
[root@node2 ~]# tar -xf harbor-offline-installer-v2.4.3.tgz -C /usr/local
[root@node2 ~]# cd /usr/local/harbor/
[root@node2 harbor]# ls
common.sh  harbor.v2.4.3.tar.gz  harbor.yml.tmpl  install.sh  LICENSE  prepare

# 備份組態檔並進行設定
[root@node2 harbor]# cp harbor.yml.tmpl harbor.yml
[root@node2 harbor]# vim harbor.yml
......
hostname: 192.168.111.138		#修改為當前主機的IP或域名
......
# https related config
#https:					#註釋https服務
  # https port for harbor, default is 443
  # port: 443
  # The path of cert and key files for nginx
  #certificate: /your/certificate/path
  #private_key: /your/private/key/path

# 執行安裝指令碼
[root@node2 harbor]# ./install.sh 
[Step 0]: checking if docker is installed ...
Note: docker version: 20.10.17
[Step 1]: checking docker-compose is installed ...
Note: docker-compose version: 2.7.0
[Step 2]: loading Harbor images ...
✔ ----Harbor has been installed and started successfully.----
[root@node2 harbor]# ss -anlt
State       Recv-Q      Send-Q           Local Address:Port            Peer Address:Port      Process      
LISTEN      0           128                    0.0.0.0:22                   0.0.0.0:*                      
LISTEN      0           128                  127.0.0.1:1514                 0.0.0.0:*                      
LISTEN      0           128                    0.0.0.0:80                   0.0.0.0:*                      
LISTEN      0           128                       [::]:22                      [::]:*                      
LISTEN      0           128                       [::]:80                      [::]:*    
[root@node2 harbor]# docker ps -a
CONTAINER ID   IMAGE                                COMMAND                  CREATED         STATUS                   PORTS                                   NAMES
828ec6d101a8   goharbor/nginx-photon:v2.4.3         "nginx -g 'daemon of…"   2 minutes ago   Up 2 minutes (healthy)   0.0.0.0:80->8080/tcp, :::80->8080/tcp   nginx
......

# 使用docker-compose管理(需要進到harbor目錄中)
[root@node2 harbor]# docker-compose stop
[+] Running 9/9
 ⠿ Container harbor-jobservice  Stopped                                                               0.2s
 ⠿ Container registryctl        Stopped                                                              10.1s
 ⠿ Container nginx              Stopped                                                               0.3s
 ⠿ Container harbor-portal      Stopped                                                               0.2s
 ⠿ Container harbor-core        Stopped                                                               0.1s
 ⠿ Container redis              Stopped                                                               0.3s
 ⠿ Container harbor-db          Stopped                                                               0.2s
 ⠿ Container registry           Stopped                                                               0.1s
 ⠿ Container harbor-log         Stopped                                                              10.1s
[root@node2 harbor]# docker-compose start
[+] Running 9/9
 ⠿ Container harbor-log         Started                                                               0.5s
 ⠿ Container harbor-db          Started                                                               1.4s
 ⠿ Container redis              Started                                                               1.2s
 ⠿ Container registryctl        Started                                                               1.3s
 ⠿ Container registry           Started                                                               1.4s
 ⠿ Container harbor-portal      Started                                                               0.9s
 ⠿ Container harbor-core        Started                                                               0.5s
 ⠿ Container harbor-jobservice  Started                                                               0.9s
 ⠿ Container nginx              Started                                                               0.8s
[root@node2 harbor]# ss -anlt
State       Recv-Q      Send-Q           Local Address:Port            Peer Address:Port      Process      
LISTEN      0           128                    0.0.0.0:22                   0.0.0.0:*                      
LISTEN      0           128                  127.0.0.1:1514                 0.0.0.0:*                      
LISTEN      0           128                    0.0.0.0:80                   0.0.0.0:*                      
LISTEN      0           128                       [::]:22                      [::]:*                      
LISTEN      0           128                       [::]:80                      [::]:*    

# 需要寫一個開啟自動啟動的指令碼,否則重啟不會啟動
[root@node2 harbor]# vim startall.sh
#!/bin/bash
  
cd /usr/local/harbor
docker-compose stop && docker-compose start

# 給指令碼執行許可權
[root@node2 harbor]# chmod +x startall.sh 
[root@node2 harbor]# ll startall.sh 
-rwxr-xr-x. 1 root root 77 Aug 11 21:15 startall.sh

# /etc/rc.local是系統啟動之後最後一個執行的檔案
[root@node2 harbor]# ll /etc/rc.local 
lrwxrwxrwx. 1 root root 13 Dec  2  2020 /etc/rc.local -> rc.d/rc.local
[root@node2 harbor]# ll /etc/rc.d/rc.local 
-rw-r--r--. 1 root root 513 Aug 11 21:13 /etc/rc.d/rc.local

# 被連結檔案也需要有執行許可權
[root@node2 harbor]# chmod +x /etc/rc.d/rc.local 
[root@node2 harbor]# ll /etc/rc.d/rc.local 
-rwxr-xr-x. 1 root root 513 Aug 11 21:13 /etc/rc.d/rc.local

# 在/etc/rc.d/rc.local里加上執行啟動指令碼的命令,就會開啟開機自動啟動
[root@node2 harbor]# vim /etc/rc.d/rc.local 
#!/bin/bash
/bin/bash /usr/local/harbor/startall.sh

# 重啟測試
[root@node2 ~]# reboot
[root@node2 ~]# ss -anlt
State       Recv-Q      Send-Q           Local Address:Port            Peer Address:Port      Process      
LISTEN      0           128                    0.0.0.0:80                   0.0.0.0:*                      
LISTEN      0           128                    0.0.0.0:22                   0.0.0.0:*                      
LISTEN      0           128                  127.0.0.1:1514                 0.0.0.0:*                      
LISTEN      0           128                       [::]:80                      [::]:*                      
LISTEN      0           128                       [::]:22                      [::]:*                      
[root@node2 ~]# docker ps -a
CONTAINER ID   IMAGE                                COMMAND                  CREATED       STATUS                        PORTS                                   NAMES
828ec6d101a8   goharbor/nginx-photon:v2.4.3         "nginx -g 'daemon of…"   2 hours ago   Up About a minute (healthy)   0.0.0.0:80->8080/tcp, :::80->8080/tcp   nginx

使用IP登入管理Harbor

預設使用者名稱:admin 預設密碼:Harbor12345

登入成功介面:

Harbor使用方法

系統管理---使用者管理---建立使用者

輸入使用者資訊

建立使用者成功---並將其設定為管理員

點選專案

點選推播命令可以檢視幫助

上傳映象

# 登入到倉庫
[root@node2 ~]# docker login 192.168.111.138
Username: admin
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

# 上傳映象
[root@node2 ~]# docker tag busybox:latest 192.168.111.138/library/runtim:v1
[root@node2 ~]# docker images
REPOSITORY                       TAG       IMAGE ID       CREATED        SIZE
......
192.168.111.138/library/runtim   v1        beae173ccac6   7 months ago   1.24MB
[root@node2 ~]# docker push 192.168.111.138/library/runtim:v1 
The push refers to repository [192.168.111.138/library/runtim]
01fd6df81c8e: Pushed 
v1: digest: sha256:62ffc2ed7554e4c6d360bce40bbcf196573dd27c4ce080641a2c59867e732dee size: 527

上傳成功

拉取映象測試

# 刪除原來的映象
[root@node2 ~]# docker rmi 192.168.111.138/library/runtim:v1

# 拉取倉庫裡的映象
[root@node2 ~]# docker pull 192.168.111.138/library/runtim:v1
v1: Pulling from library/runtim
Digest: sha256:62ffc2ed7554e4c6d360bce40bbcf196573dd27c4ce080641a2c59867e732dee
Status: Downloaded newer image for 192.168.111.138/library/runtim:v1
192.168.111.138/library/runtim:v1
[root@node2 ~]# docker images
REPOSITORY     TAG       IMAGE ID       CREATED        SIZE
.....
192.168.111.138/library/runtim  v1 beae173ccac6 7 months ago  1.24MB
.....

使用Harbor的注意事項:

  1. 在使用者端上傳映象時一定要記得執行docker login進行使用者認證,否則無法直接push
  2. 在使用者端使用的時候如果不是用的https則必須要在使用者端的/etc/docker/daemon.json組態檔中設定insecure-registries引數
  3. 資料存放路徑應在組態檔中設定到一個容量比較充足的共用儲存中
  4. Harbor是使用docker-compose命令來管理的,如果需要停止Harbor也應用docker-compose stop來停止,其他引數請--help