乾貨|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配置
配置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”,會有驚喜呈上。(各位看官請原諒此等無恥求關注行為…)