在centos下部署docker內網私服

來源:互聯網
上載者:User

標籤:

 

 

 

Docker內網私服:docker-registry with nginx & ssl on centos

docker-registry既然也是軟體應用,自然最簡單的方法就是使用官方提供的已經部署好的鏡像registry。官方文檔中也給出了建議,直接運行sudo docker run -p 5000:5000 registry命令。這樣確實能啟動一個registry伺服器,但是所有上傳的鏡像其實都是由docker容器管理,放在了/var/lib/docker/....某個目錄下。而且一旦刪除容器,鏡像也會被刪除。因此,我們需要想辦法告訴docker容器鏡像應該存放在哪裡。registry鏡像中啟動後鏡像預設位置是/tmp/registry,因此直接映射這個位置即可,比如到原生/opt/data/registry目錄下。

2. 在CentOS上搭建docker私服2.1 安裝 docker-registry

方法有多種,直接運行下面的命令:

# docker run -d -e SETTINGS_FLAVOR=dev -e STORAGE_PATH=/tmp/registry -v /opt/data/registry:/tmp/registry  -p 5000:5000 registry

如果本地沒有拉取過docker-registry,則首次運行會pull registry,運行時會映射路徑和連接埠,以後就可以從/opt/data/registry下找到私人倉庫都存在哪些鏡像,通過主機的哪個連接埠可以訪問。
你也可以把項目https://github.com/docker/docker-registry.git複製到本地,然後使用Dockerfile來build鏡像:

# git clone https://github.com/docker/docker-registry.git# cd docker-registry && mkdir -p /opt/data/registry# docker build -t "local-sean" .build完成後,就可以運行這個docker-registry我們先配置自己的config.yml檔案,第一種方法是直接在run的時候指定變數# cp config/config_sample.yml /opt/data/registry/config.yml# vi /opt/data/registry/config.yml##這裡可以設定本機存放區SETTINGS_FLAVOR=dev,local STORAGE_PATH:/tmp/registry等待# docker run -d -v /opt/data/registry:/tmp/registry -p 5000:5000 -e  DOCKER_REGISTRY_CONFIG=/tmp/registry/config.yml registry或docker run -d -e SETTINGS_FLAVOR=dev -e STORAGE_PATH=/tmp/registry -v /db/docker-images:/tmp/registry -p 5000:5000 registry
2.2 用戶端使用

要從私服上擷取鏡像或向私服提交鏡像,現在變得非常簡單,只需要在倉庫前面加上私服的地址和連接埠,形如172.29.88.222:5000/centos6。注意,這裡可以選擇不使用IP,而是用hostname,如registry.domain.com:5000,但不能僅用不帶.的主機名稱registry,docker會認為registry是使用者名稱,建議使用帶網域名稱的hostname加port來表示。

於是在另外一台要使用docker的主機上就可以通過這台私服拉取和推送鏡像了:

從私服上搜尋存在哪些可用鏡像# curl -X GET http://sean.domain.com:5000/v1/search{"num_results": 2, "query": "", "results": [{"description": "", "name": "library/centos6"}, {"description": "", "name": "library/nginx"}]}按條件搜尋nginx# curl -X GET http://sean.domain.com:5000/v1/search?q=centos6拉取image到本地docker pull library/centos6## 本地對份鏡像啟動起來,形成container## 給container去另外一個名字# docker tag 68edf809afe7 registry.domain.com:5000/centos6-test## 最後將新的docker images推送到私服上docker push registry.domain.com:5000/centos6-test

第一次push到私服上時會提示使用者名稱、密碼和郵箱,建立即可。也可以在docker私服端加入認證機制。

3. 加入nginx認證

(請在實際操作以前,先閱讀完本節,再確定是否在前端加入nginx)

3.1 安裝及配置nginx

從上面的過程可以看到,除非防火牆限制,否則任何主機可以建立帳號並想私服推送鏡像,更安全的做法是在外層加入登入認證機制。

最好安裝1.4.x版本,不然下面的有些配置可能會不相容# yum install nginx建立兩個登入使用者# htpasswd -c /etc/nginx/docker-registry.htpasswd seanNew password: Re-type new password: Adding password for user sean# htpasswd -c /etc/nginx/docker-registry.htpasswd itsection

為了讓nginx使用這個密碼檔案,並且轉寄8080連接埠的請求到Docker Registry,新增nginx設定檔
vi /etc/nginx/sites-enabled/docker-registry

# For versions of Nginx > 1.3.9 that include chunked transfer encoding support# Replace with appropriate values where necessaryupstream docker-registry { server localhost:5000;}server { listen 8080; server_name sean.domain.com;  -- your registry server_name # ssl on; # ssl_certificate /etc/ssl/certs/docker-registry; # ssl_certificate_key /etc/ssl/private/docker-registry; proxy_set_header Host       $http_host;   # required for Docker client sake proxy_set_header X-Real-IP  $remote_addr; # pass on real client IP client_max_body_size 0; # disable any limits to avoid HTTP 413 for large image uploads # required to avoid HTTP 411: see Issue #1486 (https://github.com/dotcloud/docker/issues/1486) chunked_transfer_encoding on; location / {     # let Nginx know about our auth file     auth_basic              "Restricted";     auth_basic_user_file    docker-registry.htpasswd;     proxy_pass http://docker-registry; } location /_ping {     auth_basic off;     proxy_pass http://docker-registry; }   location /v1/_ping {     auth_basic off;     proxy_pass http://docker-registry; }}
讓nginx來使用這個virtual-host# ln -s /etc/nginx/sites-enabled/docker-registry /etc/nginx/conf.d/docker-registry.conf重啟nginx來啟用虛擬機器主機的配置# service nginx restart
3.2 加入認證後使用docker-registry

此時主機的5000連接埠應該通過防火牆禁止訪問(或者在docker run連接埠映射時只監聽迴環介面的IP -p 127.0.0.1:5000:5000)。

# curl localhost:5000"docker-registry server (dev) (v0.8.1)"

如果直接存取訪問將得到未授權的資訊:

# curl localhost:8080<html><head><title>401 Authorization Required</title></head><body bgcolor="white"><center><h1>401 Authorization Required</h1></center><hr><center>nginx/1.4.7</center></body></html>

帶使用者認證的docker-registry:

# curl http://sean:[email protected]:8080/v1/search{"num_results": 2, "query": "", "results": [{"description": "", "name": "library/centos6"}, {"description": "", "name": "library/nginx"}]}# docker login registry.domain.com:8080Username: seanPassword: Email: [email protected]n.comLogin Succeeded# docker pull registry.domain.com:8080/library/centos6

不出意外的話,上面的docker pull會失敗:

# docker pull registry.domain.com:8080/library/centos6Pulling repository registry.domain.com:8080/library/centos62014/11/11 21:00:25 Could not reach any registry endpoint# docker push registry.domain.com:8080/ubuntu:seanThe push refers to a repository [registry.domain.com:8080/ubuntu] (len: 1)Sending image listPushing repository registry.domain.com:8080/ubuntu (1 tags)2014/11/12 08:11:32 HTTP code 401, Docker will not send auth headers over HTTP.nginx日誌2014/11/12 07:03:49 [error] 14898#0: *193 no user/password was provided for basic authenticatGET /v1/repositories/library/centos6/tags HTTP/1.1", host: "registry.domain.com:8080"

本文後的第1篇參考文檔沒有出現這個問題,但評論中有提及。
有人說是backend storage的問題,這裡是本機存放區鏡像,不應該。經過查閱大量資料,並反覆操作驗證,是docker-registry版本的問題。從v0.10.0開始,docker login雖然Succeeded,但pullpush的時候,~/.dockercfg下的使用者登入資訊將不允許通過HTTP明文傳輸。(如果你願意可以查看v0.10.0的源碼 registry.go,在分支v0.9.1及以前是沒有HTTP code 401, Docker will not send auth headers over HTTP的
目前的辦法三個:

  • 撤退,這就是為什麼先說明在操作前線查看到這的原因了
  • 換成v0.9.1及以下版本。現在都v1.3.1了,我猜你不會這麼做
  • 修改源碼session.go,去掉相應的判斷行,然後git下來重新安裝。我猜你更不會這麼做
  • 安裝SSL認證,使用HTTPS傳輸。這是明智的選擇,新版本docker也推薦我們這麼做,往下看。
3.3 為nginx安裝ssl認證

首先開啟nginx設定檔中ssl的三行注釋

# vi /etc/nginx/conf.d/docker-registry.conf...server { listen 8000; server_name registry.domain.com; ssl on; ssl_certificate /etc/nginx/ssl/nginx.crt; ssl_certificate_key /etc/nginx/ssl/nginx.key;...

儲存之後,nginx會分別從/etc/nginx/ssl/nginx.crt/etc/nginx/ssl/nginx.key讀取ssl認證和私密金鑰。如果你自己願意花錢買一個ssl認證,那就會變得非常簡單,把認證和私密金鑰拷貝成上面一樣即可。關於SSL以及簽署ssl認證,請參考其他文章。
這裡我們自簽署一個ssl認證,把當前系統作為(私人)憑證發行中心(CA)。

建立存放認證的目錄

# mkdir /etc/nginx/ssl

確認CA的一些設定檔

# vi /etc/pki/tls/openssl.cnf...[ CA_default ]dir             = /etc/pki/CA           # Where everything is keptcerts           = $dir/certs            # Where the issued certs are keptcrl_dir         = $dir/crl              # Where the issued crl are keptdatabase        = $dir/index.txt        # database index file.#unique_subject = no                    # Set to ‘no‘ to allow creation of                                        # several ctificates with same subject.new_certs_dir   = $dir/newcerts         # default place for new certs.certificate     = $dir/cacert.pem       # The CA certificateserial          = $dir/serial           # The current serial numbercrlnumber       = $dir/crlnumber        # the current crl number                                        # must be commented out to leave a V1 CRLcrl             = $dir/crl.pem          # The current CRLprivate_key     = $dir/private/cakey.pem # The private keyRANDFILE        = $dir/private/.rand    # private random number file...default_days    = 3650                  # how long to certify for...[ req_distinguished_name ]countryName                     = Country Name (2 letter code)countryName_default             = CNcountryName_min                 = 2countryName_max                 = 2stateOrProvinceName             = State or Province Name (full name)stateOrProvinceName_default     = GD...[ req_distinguished_name ]部分主要是頒證時一些預設的值,可以不動

(1) 產生根密鑰

# cd /etc/pki/CA/# openssl genrsa -out private/cakey.pem 2048

為了安全起見,修改cakey.pem私密金鑰檔案許可權為600或400,也可以使用子shell產生( umask 077; openssl genrsa -out private/cakey.pem 2048 ),下面不再重複。

(2) 產生根憑證

# openssl req -new -x509 -key private/cakey.pem -out cacert.pem

會提示輸入一些內容,因為是私人的,所以可以隨便輸入,最好記住能與後面保持一致。上面的自簽認證cacert.pem應該產生在/etc/pki/CA下。

(3) 為我們的nginx web伺服器產生ssl密鑰

# cd /etc/nginx/ssl# openssl genrsa -out nginx.key 2048

我們的CA中心與要申請認證的伺服器是同一個,否則應該是在另一台需要用到認證的伺服器上產生。

(4) 為nginx產生認證簽署請求

# openssl req -new -key nginx.key -out nginx.csr...Country Name (2 letter code) [AU]:CNState or Province Name (full name) [Some-State]:GDLocality Name (eg, city) []:SZOrganization Name (eg, company) [Internet Widgits Pty Ltd]:COMPANYOrganizational Unit Name (eg, section) []:IT_SECTIONCommon Name (e.g. server FQDN or YOUR name) []:your.domain.comEmail Address []:Please enter the following ‘extra‘ attributesto be sent with your certificate requestA challenge password []:An optional company name []:...

同樣會提示輸入一些內容,其它隨便,除了Commone Name一定要是你要授予認證的伺服器網域名稱或主機名稱,challenge password不填。

(5) 私人CA根據請求來簽發認證

# openssl ca -in nginx.csr -out nginx.crt

上面簽發過程其實預設使用了-cert cacert.pem -keyfile cakey.pem,這兩個檔案就是前兩步產生的位於/etc/pki/CA下的根密鑰和根憑證。

到此我們已經擁有了建立ssl安全連線所需要的所有檔案,並且伺服器的crt和key都位於配置的目錄下,唯有根憑證cacert.pem位置不確定放在CentOS6下的哪個地方。
經驗證以下幾個位置不行:(Adding trusted root certificates to the server)
/etc/pki/ca-trust/source/anchors/etc/pki/ca-trust/source/etc/pki/ca-trust/extracted
/etc/pki/ca-trust/extracted/pem//etc/pki/tls/certs/cacert.crt
都會報錯:

# docker login https://registry.domain.com:8000Username (sean): sean2014/11/14 02:32:48 Error response from daemon: Invalid Registry endpoint: Get https://registry.domain.com:8000/v1/_ping: x509: certificate signed by unknown authority# curl https://sean:[email protected]:8000/curl: (60) Peer certificate cannot be authenticated with known CA certificatesMore details here: http://curl.haxx.se/docs/sslcerts.htmlcurl performs SSL certificate verification by default, using a "bundle" of Certificate Authority (CA) public keys (CA certs). If the default bundle file isn‘t adequate, you can specify an alternate file using the --cacert option.If this HTTPS server uses a certificate signed by a CA represented in the bundle, the certificate verification probably failed due to a problem with the certificate (it might be expired, or the name might not match the domain name in the URL).If you‘d like to turn off curl‘s verification of the certificate, use the -k (or --insecure) option.

(6) 目前讓根憑證起作用的只發現一個辦法:

# cp /etc/pki/tls/certs/ca-bundle.crt{,.bak}    備份以防出錯# cat /etc/pki/CA/cacert.pem >> /etc/pki/tls/certs/ca-bundle.crt# curl https://sean:[email protected]:8000"docker-registry server (dev) (v0.8.1)"

cacert.pem根憑證追加到ca-bundle.crt後一定要重啟docker後台進程才行。

如果docker login依然報錯certificate signed by unknown authority,參考Running Docker with https,啟動docker後台進程時指定信任的CA根憑證:

# docker -d --tlsverify --tlscacert /etc/pki/CA/cacert.pem或者將cacert.pem拷貝到~/.docker/ca.pem# mkdir ~/.docker && cp /etc/pki/CA/cacert.pem ~/.docker/ca.pem# docker -d最好重啟一下registry# docker restart <registry_container_id> 

上面用“如果”是因為一開始總提示certificate signed by unknown authority,有人說將根憑證放在/etc/docker/certs.d下,還有人說啟動docker daemon收加入--insecure-registry .. 但終究是因為版本差異不成功。但後來又奇蹟般的不需要--tlscacert就好了。
這個地方掙紮了很久,重點關注一下這個下面幾個issue:

  • https://github.com/docker/docker-registry/issues/82
  • https://github.com/docker/docker/pull/2687
  • https://github.com/docker/docker/pull/2339

(7) 最終搞定:

# docker login https://registry.domain.com:8000Username: seanPassword: Email: [email protected]Login Succeeded# curl https://sean:[email protected]:8000"docker-registry server (dev) (v0.8.1)"# docker push registry.domain.com:8000/centos6:test_privThe push refers to a repository [registry.domain.com:8000/centos6] (len: 1)Sending image listPushing repository registry.domain.com:8000/centos6 (1 tags)511136ea3c5a: Image successfully pushed 5b12ef8fd570: Image successfully pushed 68edf809afe7: Image successfully pushed 40627956f44c: Image successfully pushed Pushing tag for rev [40627956f44c] on {https://registry.domain.com:8000/v1/repositories/centos6/tags/test_priv}

但還有一個小問題沒解決,雖然已經可以正常使用,但每次請求在nginx的error.log中還是會有[error] 8299#0: *27 no user/password was provided for basic authentication,應該是這個版本docker暫未解決的bug。

3.3 其它問題

(1) docker後台進程意外中斷後,重新docker start <container_id>報錯

# docker start b36bd796bd3dError: Cannot start container b36bd796bd3d: Error getting container b36bd796bd3d463c4fedb70d98621e7318ec3d5cd14b2f60b1d182ad3cbcc652 from driver devicemapper: Error mounting ‘/dev/mapper/docker-253:0-787676-b36bd796bd3d463c4fedb70d98621e7318ec3d5cd14b2f60b1d182ad3cbcc652‘ on ‘/var/lib/docker/devicemapper/mnt/b36bd796bd3d463c4fedb70d98621e7318ec3d5cd14b2f60b1d182ad3cbcc652‘: device or resource busy2014/11/08 15:14:57 Error: failed to start one or more containers

經分析產生這個問題的原因是做了一個操作:在docker後台進程啟動的終端,繼續斷行符號後會臨時退出後台進程的日誌輸出,我就在這個shell下使用yum安裝軟體包,但由於網路原因yum卡住不動,於是我就另起了一個終端kill了這個yum進程,不知為何會影響到表面已經退出前台輸出的docker。解決辦法是umount容器的掛載點:(見這裡)

# umount /var/lib/docker/devicemapper/mnt/b36bd796bd3d463c4fedb70d98621e7318ec3d5cd14b2f60b1d182ad3cbcc652# service docker start   正常

能想到的另外一個辦法是,啟動docker後台進程時,重新導向輸出docker -d > /dev/null 2>&1(/var/log/docker已自動記錄了一份日誌)。

(2) 配置完nginx的docker-registry.conf後啟動報錯

# service nginx start[emerg] 14714#0: unknown directive "upstream" in /etc/nginx/conf.d/docker-registry.conf:4

原因是nginx版本太低,一些配置指令不相容,使用yum install nginx預設安裝了1.0.x,卸載重新下載nginx-1.4.7-1.el6.ngx.x86_64.rpm安裝解決。

(3) 網路設定代理問題
pull, push官網的鏡像時由於GFW的原因需要設定代理,但不是http_proxy而是HTTP_PROXY,對於docker來說同時設定這兩個值就會出問題,有時出於安裝軟體包的需要設定http_proxy,就會導致衝突。在docker-registry中如果忘記了當前哪一個在起作用,找遍所有問題都發現不了原因,而docker返回給我們的錯誤也難以判斷。切記~

TO-DO
如何刪除docker-registry的裡的鏡像

 

********************************************************************************************************

yum裝docker-registry的一個坑

 

docker-registry依賴的python-backports-lzma-0.0.2-5.el6.x86_64.rpm包有問題,少了package描述,需要執行:

 #echo -e ‘from pkgutil import extend_path\n__path__ = extend_path(__path__, __name__)‘>/usr/lib64/python2.6/site-packages/backports/__init__.py

**************************************************************************************

注意:

上面使用的是官方提供的Docker Hub網站來作為一個公開的集中倉庫。

然而,本地訪問Docker Hub速度往往很慢,並且很多時候我們需要一個本地的私人倉庫只供網內使用。

下面介紹在centos上安裝docker registy.

安裝依賴的庫:
sudo yum install python-devel libevent-devel python-pip gcc xz-devel
安裝docker-registry:
sudo python-pip install docker-registry[bugsnag]
運行
gunicorn --access-logfile - --debug -k gevent -b 0.0.0.0:7030 -w 1 docker_registry.wsgi:applicationorgunicorn -k gevent --max-requests 100 --graceful-timeout 3600 -t 3600 -b localhost:7070 -w 8 docker_registry.wsgi:application
用戶端使用

要從私服上擷取鏡像或向私服提交鏡像,現在變得非常簡單,只需要在倉庫前面加上私服的地址和連接埠,形如172.29.88.222:7030/centos6。

 

在centos下部署docker內網私服

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.