1. 程式人生 > >乾貨|Nginx+Portus+Registry搭建私有映象倉庫

乾貨|Nginx+Portus+Registry搭建私有映象倉庫

Portus介紹

Portus是SUSE為Docker Registry(v2)開發的一款開源的使用者前端和授權管理軟體。提供企業私有Docker Registry的使用者和許可權管理功能,並提供Web介面使得管理員能夠更加簡易的進行管理操作。可以簡單的理解為通過Portus+Registry的結合來實現企業私有的Docker Hub部署和管理。

Portus特性

安全
Portus實現私有Docker Registry中所有映象的許可權管理,針對不同的映象設定不同使用者或組的Push和Pull許可權。

使用者管理
Portus提供Web介面管理方式,可非常容易的進行使用者和組的新增、修改、授權和刪除等操作。

搜尋
Portus提供了私有倉庫內容的概覽,但是也可以通過搜尋功能更快找到需要的映象。

Portus的功能還有很多,比如LDAP支援,操作審計等等。Portus許可權管理的安全性和細粒度還算比較高,Repository層面設定不同使用者和組的許可權,使用者層面又設定了不同的角色,通過多方面的授權實現映象的安全性管理。個人覺得如果企業內部的開發測試環境需要一個私有的Registry的話,可以考慮採用Portus。

Registry v2驗證過程

Docker Client通過Docker Daemon拉取映象白話版:
\1.我要搬貨
\2.沒授權,去相關部門開單子(拿Token)
\3.我要搬貨,這是我的申請單(提交使用者名稱和密碼申請Token)
\4.核實資訊,單子蓋章(拿到Token)
\5.我要搬貨,這是授權單
\6.通過,搬走

Portus主要功能就是上面的”相關部門”(Authorization Service)了,負責使用者請求的驗證和授權功能。

環境介紹


私有”Docker Hub”整個環境的5個容器跑在一臺Docker宿主機上,並使用兩個Alias實現Portus和Registry的訪問。

  • Docker宿主機:docker04.onlyeric.com

  • 容器:
    portus_nginx_1: Nginx反向代理服務
    portus_registry_1: 私有Registry服務
    portus_web_1: Portus的Web服務
    portus_crono_1: Portus服務
    portus_db_1: Portus資料庫服務

  • Alias
    onlyeric.reg 使用者pull/push操作的映象伺服器
    portus.onlyeric.com 管理員訪問的Portus介面

環境準備

Server: 內網KVM虛機
OS: CentOS 7.2
IP: 192.168.2.14
Docker Engine: 1.11.2
Docker Compose: 1.7.1
Docker Images:
library/registry:2.3.1
library/mariadb:10.0.23
library/rails:4.2.2
nginx:1.10.1
(rails是構建portus的基礎映象,其他三個顧名思義了)

Alias:
192.168.2.14 onlyeric.reg
192.168.2.14 portus.onlyeric.com
(由於內網沒有配置DNS伺服器,所以需要在客戶端和服務端都新增以上記錄到hosts檔案)

Docker Engine配置:
“--insecure-registry onlyeric.reg”

在以上準備工作搞定之後就可以開始進行Portus的部署了。需要的Image可以不用提前準備,因為SUSE提供的部署指令碼已含有映象的下載內容。但是考慮到國內訪問Docker Hub經常抽風,個人建議先把映象給下載或者從哪兒Load過來。

安裝部署

Portus指令碼修改

預設的Portus腳本里不含nginx容器和配置,Portus和Registry的訪問需要加埠。以下配置的變更主要是為了實現Nginx到Potus和Registry埠轉發,實現不帶埠(80埠)的訪問。

下載Portus指令碼
# git clone git clone https://github.com/SUSE/Portus.git

修改Gemfile

1
2
3
4
# vi Gemfile
#source "https://rubygems.org"
source "http://rubygems.org"
(國外的伺服器無需修改)

建立nginx配置目錄
# mkdir nginx/conf.d

建立nginx配置檔案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# pwd
/root/Portus/nginx/conf.d

Portus反向代理配置檔案
# vi portus.conf
server {
    listen 0.0.0.0:80;
    server_name portus.onlyeric.com;

    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_redirect off;
        proxy_pass http://web:3000/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 900s;
        }


    access_log /var/log/nginx/portus.access.log main;
    error_log /var/log/nginx/portus.error.log error;

}  

registry反向代理配置檔案
# vi registry.conf
upstream onlyeric.reg {
  server registry:5000;
}

map $upstream_http_docker_distribution_api_version $docker_distribution_api_version {
  'registry/2.0' '';
  default registry/2.0;
}

server {
  listen 80;
  server_name onlyeric.reg;

  client_max_body_size 0;

  chunked_transfer_encoding on;

  location /v2/ {
    if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
      return 404;
    }

    add_header 'Docker-Distribution-Api-Version' $docker_distribution_api_version always;

    proxy_pass                          http://onlyeric.reg;
    proxy_set_header  Host              $http_host;   # required for docker client's sake
    proxy_set_header  X-Real-IP         $remote_addr; # pass on real client's IP
    proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Proto $scheme;
    proxy_read_timeout                  900;
  }
}

(配置檔案中使用到的registry和web是在容器層面做過link的)

修改compose檔案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# pwd
/root/Portus/compose  

# vi docker-compose.yml.template  
web:
  build: .
  command: puma -b tcp://0.0.0.0:3000 -w 3
  environment:
    - PORTUS_MACHINE_FQDN_VALUE=EXTERNAL_IP
    - PORTUS_DB_HOST=portus_db_1
  volumes:
    - .:/portus
  ports:
    - 3000:3000
  links:
    - db
  extra_hosts:
    - "onlyeric.reg:192.168.2.14"
    - "portus.onlyeric.com:192.168.2.14"

crono:
  image: portus_web
  entrypoint: bin/crono
  environment:
    - PORTUS_MACHINE_FQDN=EXTERNAL_IP
    - PORTUS_DB_HOST=portus_db_1
  volumes:
    - .:/portus
  links:
    - db
  extra_hosts:
    - "onlyeric.reg:192.168.2.14"
    - "portus.onlyeric.com:192.168.2.14"

db:
  image: library/mariadb:10.0.23
  environment:
    MYSQL_ROOT_PASSWORD: portus
  extra_hosts:
    - "onlyeric.reg:192.168.2.14"
    - "portus.onlyeric.com:192.168.2.14"

registry:
  image: library/registry:2.3.1
  volumes:
    - /registry:/registry_data
    - ./compose/registry/portus.crt:/etc/docker/registry/portus.crt:ro
    - ./compose/registry/config.yml:/etc/docker/registry/config.yml:ro
  ports:
    - 5000:5000
    - 5001:5001 # required to access debug service
  links:
    - web
  extra_hosts:
    - "onlyeric.reg:192.168.2.14"
    - "portus.onlyeric.com:192.168.2.14"

nginx:
 image: nginx:1.10.1
 links:
   - registry
   - web
 volumes:
   - ./nginx/conf.d:/etc/nginx/conf.d
 ports:
   - 80:80
 extra_hosts:
   - "onlyeric.reg:192.168.2.14"
   - "portus.onlyeric.com:192.168.2.14"

(新增nginx容器,並將alias的解析新增到所有容器中。其中將registry容器中images存放的目錄給mount到Docker host的檔案系統上)

修改registry配置檔案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# pwd
/root/Portus/compose/registry  

# vi config.yml.template  

version: 0.1
storage:
  filesystem:
    rootdirectory: /registry_data
  delete:
    enabled: true
http:
  addr: 0.0.0.0:5000
  debug:
    addr: 0.0.0.0:5001
auth:
  token:
    realm: http://EXTERNAL_IP:3000/v2/token
    service: EXTERNAL_IP
    issuer: EXTERNAL_IP
    rootcertbundle: /etc/docker/registry/portus.crt
notifications:
  endpoints:
    - name: portus
      url: http://EXTERNAL_IP:3000/v2/webhooks/events
      timeout: 500ms
      threshold: 5
      backoff: 1s

(將service後的5000埠去掉)

環境部署

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# pwd
/root/Portus  

# ./compose-setup.sh -e onlyeric.reg

###########
# WARNING #
###########

This deployment method is intended for testing/development purposes.
To deploy Portus on production please take a look at: http://port.us.org/documentation.html

The setup will destroy the containers used by Portus, removing also their volumes.
Are you sure to delete all the data? (Y/N) [Y] Y  

.
.
.

###################
#     SUCCESS     #
###################

Make sure port 3000 and 5000 are open on host onlyeric.reg

Open http://onlyeric.reg:3000 with your browser and perform the following steps:

  1. Create an admin account
  2. You will be redirected to a page where you have to register the registry. In this form:
    - Choose a custom name for the registry.
    - Enter onlyeric.reg:5000 as the hostname.
    - Do *not* check the "Use SSL" checkbox, since this setup is not using SSL.

Perform the following actions on the docker hosts that need to interact with your registry:

  - Ensure the docker daemon is started with the '--insecure-registry onlyeric.reg:5000'
  - Perform the docker login.

To authenticate against your registry using the docker cli do:

  $ docker login -u <portus username> -p <password> -e <email> onlyeric.reg:5000

To push an image to the private registry:

  $ docker pull busybox
  $ docker tag busybox onlyeric.reg:5000/<username>busybox
  $ docker push onlyeric.reg:5000/<username>busybox

確認指令碼執行的WARNING很友善的提示了該部署方式主要是用於開發測試環境,個人猜測原因可能是沒有啟用SSL安全配置。

部署的過程主要是使用docker compose來基於編輯好的compose檔案啟動環境。涵蓋portus_web:latest映象的build以及5個容器的啟動。如果是在國內的網路環境部署的話整個過程非常長,因為portus_web映象構建的時候需要更新很多軟體包。如果之前沒將需要的images準備好的話,該過程可能會更長。國外伺服器的話大概30分鐘之內可以搞定,Docker的魅力就在此了。任何應用不需要過多的安裝和配置,拿著映象啟動成容器直接用就行。

部署成功後會提示SUCCESS並提供了很多連結和操作說明。這裡需要注意的是由於我們使用了Nginx做了Portus和Registry的反向代理,所以在訪問應用時後面的埠可以省略。

按照之前的規劃:
Portus Web的Link為
Registry為onlyeric.reg

Portus配置

建立admin帳號

(帳號密碼任意設定)

配置Registry
在首次登入Portus的時候會自動彈出配置Registry的視窗

(Name任意,Hostname為onlyeric.reg)

(配置成功後會直接跳到如上介面)

基本驗證

登陸測試

1
2
3
# docker login -u onlyeric -p zaq12wsx! onlyeric.reg
Login Succeeded  
(登入成功)

Push測試

1
2
3
4
5
6
7
8
9
# docker tag busybox:latest onlyeric.reg/onlyeric/busybox:latest  
(Tag測試所需映象,REGISTRY_NAME/USERNAME/IMAGE_NAME/IMAGE_TAG)

# docker push onlyeric.reg/onlyeric/busybox:latest
The push refers to a repository [onlyeric.reg/onlyeric/busybox]
5f70bf18a086: Pushed 
8ac8bfaff55a: Pushed 
latest: digest: sha256:507bc9f5e7844d90c630f141a93b073473e24bd0b27daef574ffa93f97d01181 size: 733  
(映象上傳成功)

稍等片刻之後Portus的Web介面也可以看到上傳成功的映象

Pull測試

1
2
3
4
5
6
7
8
9
# docker rmi onlyeric.reg/onlyeric/busybox:latest
Untagged: onlyeric.reg/onlyeric/busybox:latest  
(刪除原有映象)

# docker pull onlyeric.reg/onlyeric/busybox:latest
latest: Pulling from onlyeric/busybox
Digest: sha256:507bc9f5e7844d90c630f141a93b073473e24bd0b27daef574ffa93f97d01181
Status: Downloaded newer image for onlyeric.reg/onlyeric/busybox:latest  
(映象下載成功)

基本許可權管理

建立使用者
Admin–>Users–>Create new user

建立使用者組
Teams–>Create new team–>users

新增使用者到組
users–>Add members–>Role(Viewer)–>test

修改Namespace所屬組
Namespaces–>onlyeric–>Edit namespace–>Team–>users

異機測試

測試前提

  • 新增hosts檔案記錄”192.168.2.14 onlyeric.reg”
  • 將引數配置”--insecure-registry onlyeric.reg”到異機的Docker並重啟服務
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# docker login -u test -p zaq12wsx! onlyeric.reg
Login Succeeded  
(登陸成功)

# docker pull onlyeric.reg/onlyeric/busybox:latest
latest: Pulling from onlyeric/busybox
8ddc19f16526: Pull complete 
a3ed95caeb02: Pull complete 
Digest: sha256:507bc9f5e7844d90c630f141a93b073473e24bd0b27daef574ffa93f97d01181
Status: Downloaded newer image for onlyeric.reg/onlyeric/busybox:latest  

# docker images|grep busybox
onlyeric.reg/onlyeric/busybox   latest              332de81782ef        3 weeks ago         1.093 MB  
(下載映象成功)

至此Nginx+Portus+Registry的部署過程及基本配置已經完成。由於此次配置的環境沒有SSL相關安全的配置,建議僅在開發測試環境使用該方案。

文末特別感謝[email protected]擎天柱和[email protected]的無損交流和傾情指導。

PS:Portus本身是支援生產環境的安全部署的,關注”小張烤茄”並回復”portus”,會有驚喜呈上。(各位看官請原諒此等無恥求關注行為…)