溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何搭建docker內(nèi)網(wǎng)私服

發(fā)布時(shí)間:2022-04-29 16:29:58 來(lái)源:億速云 閱讀:251 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要介紹“如何搭建docker內(nèi)網(wǎng)私服”,在日常操作中,相信很多人在如何搭建docker內(nèi)網(wǎng)私服問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”如何搭建docker內(nèi)網(wǎng)私服”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

主要思路:

如何搭建docker內(nèi)網(wǎng)私服

1. docker registry 說(shuō)明

關(guān)于如何創(chuàng)建和使用本地倉(cāng)庫(kù),其實(shí)已經(jīng)有很多文章介紹了。因?yàn)閐ocker技術(shù)正處于發(fā)展和完善階段,所以有些文章要么內(nèi)容已經(jīng)過(guò)時(shí),要么給出了錯(cuò)誤的配置,導(dǎo)致無(wú)法正常創(chuàng)建倉(cāng)庫(kù)。本文記錄的是個(gè)人完整的搭建過(guò)程,docker version為1.1.2。

官方提供了docker hub網(wǎng)站來(lái)作為一個(gè)公開(kāi)的集中倉(cāng)庫(kù)。然而,本地訪問(wèn)docker hub速度往往很慢,并且很多時(shí)候我們需要一個(gè)本地的私有倉(cāng)庫(kù)只供網(wǎng)內(nèi)使用。

docker倉(cāng)庫(kù)實(shí)際上提供兩方面的功能,一個(gè)是鏡像管理,一個(gè)是認(rèn)證。前者主要由項(xiàng)目來(lái)實(shí)現(xiàn),通過(guò)http服務(wù)來(lái)上傳下載;后者可以通過(guò)docker-index(閉源)項(xiàng)目或者利用現(xiàn)成認(rèn)證方案(如nginx)實(shí)現(xiàn)http請(qǐng)求管理。

docker-registry既然也是軟件應(yīng)用,自然最簡(jiǎn)單的方法就是使用官方提供的已經(jīng)部署好的鏡像registry。官方文檔中也給出了建議,直接運(yùn)行sudo docker run -p 5000:5000 registry命令。這樣確實(shí)能啟動(dòng)一個(gè)registry服務(wù)器,但是所有上傳的鏡像其實(shí)都是由docker容器管理,放在了/var/lib/docker/….某個(gè)目錄下。而且一旦刪除容器,鏡像也會(huì)被刪除。因此,我們需要想辦法告訴docker容器鏡像應(yīng)該存放在哪里。registry鏡像中啟動(dòng)后鏡像默認(rèn)位置是/tmp/registry,因此直接映射這個(gè)位置即可,比如到本機(jī)的/opt/data/registry目錄下。

2. 在centos上搭建docker私服

2.1 安裝docker-registry

方法有多種,直接運(yùn)行下面的命令:

復(fù)制代碼 代碼如下:

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

如果本地沒(méi)有拉取過(guò)docker-registry,則首次運(yùn)行會(huì)pull registry,運(yùn)行時(shí)會(huì)映射路徑和端口,以后就可以從/opt/data/registry下找到私有倉(cāng)庫(kù)都存在哪些鏡像,通過(guò)主機(jī)的哪個(gè)端口可以訪問(wèn)。

你也可以把項(xiàng)目  克隆到本地,然后使用dockerfile來(lái)build鏡像:

# git clone https://github.com/docker/docker-registry.git
# cd docker-registry && mkdir -p /opt/data/registry
# docker build -t "local-sean" .

build完成后,就可以運(yùn)行這個(gè)docker-registry

我們先配置自己的config.yml文件,第一種方法是直接在run的時(shí)候指定變量

# cp config/config_sample.yml /opt/data/registry/config.yml
# vi /opt/data/registry/config.yml
##這里可以設(shè)置本地存儲(chǔ)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 客戶端使用

要從私服上獲取鏡像或向私服提交鏡像,現(xiàn)在變得非常簡(jiǎn)單,只需要在倉(cāng)庫(kù)前面加上私服的地址和端口,形如172.29.88.222:5000/centos6。注意,這里可以選擇不使用ip,而是用hostname,如registry.domain.com:5000,但不能僅用不帶.的主機(jī)名registry,docker會(huì)認(rèn)為registry是用戶名,建議使用帶域名的hostname加port來(lái)表示。

于是在另外一臺(tái)要使用docker的主機(jī)上就可以通過(guò)這臺(tái)私服拉取和推送鏡像了:

從私服上搜索存在哪些可用鏡像

復(fù)制代碼 代碼如下:

# curl -x get
{"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

## 本地對(duì)份鏡像啟動(dòng)起來(lái),形成container
## 給container去另外一個(gè)名字
# docker tag 68edf809afe7 registry.domain.com:5000/centos6-test

## 最后將新的docker images推送到私服上
docker push registry.domain.com:5000/centos6-test

第一次push到私服上時(shí)會(huì)提示用戶名、密碼和郵箱,創(chuàng)建即可。也可以在docker私服端加入認(rèn)證機(jī)制。

3. 加入nginx認(rèn)證

(請(qǐng)?jiān)趯?shí)際操作以前,先閱讀完本節(jié),再確定是否在前端加入nginx)

3.1 安裝及配置nginx

從上面的過(guò)程可以看到,除非防火墻限制,否則任何主機(jī)可以創(chuàng)建賬號(hào)并想私服推送鏡像,更安全的做法是在外層加入登錄認(rèn)證機(jī)制。

最好安裝1.4.x版本,不然下面的有些配置可能會(huì)不兼容

# yum install nginx

創(chuàng)建兩個(gè)登錄用戶

# htpasswd -c /etc/nginx/docker-registry.htpasswd sean
new password: 
re-type new password: 
adding password for user sean

# htpasswd /etc/nginx/docker-registry.htpasswd itsection

為了讓nginx使用這個(gè)密碼文件,并且轉(zhuǎn)發(fā)8080端口的請(qǐng)求到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 necessary

upstream 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來(lái)使用這個(gè)virtual-host

# ln -s /etc/nginx/sites-enabled/docker-registry /etc/nginx/conf.d/docker-registry.conf

重啟nginx來(lái)激活虛擬主機(jī)的配置

# service nginx restart

3.2 加入認(rèn)證后使用docker-registry

此時(shí)主機(jī)的5000端口應(yīng)該通過(guò)防火墻禁止訪問(wèn)(或者在docker run端口映射時(shí)只監(jiān)聽(tīng)回環(huán)接口的ip -p 127.0.0.1:5000:5000)。

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

如果直接訪問(wèn)訪問(wèn)將得到未授權(quán)的信息:

# 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>

帶用戶認(rèn)證的docker-registry:

# curl http://sean:sean@sean.domain.com:8080/v1/search
{"num_results": 2, "query": "", "results": [{"description": "", "name": "library/centos6"}, {"description": "", "name": "library/nginx"}]}

# docker login registry.domain.com:8080
username: sean
password: 
email: zhouxiao@domain.com
login succeeded

# docker pull registry.domain.com:8080/library/centos6

不出意外的話,上面的docker pull會(huì)失敗:

# docker pull registry.domain.com:8080/library/centos6
pulling repository registry.domain.com:8080/library/centos6
2014/11/11 21:00:25 could not reach any registry endpoint

# docker push registry.domain.com:8080/ubuntu:sean
the push refers to a repository [registry.domain.com:8080/ubuntu] (len: 1)
sending image list
pushing 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篇參考文檔沒(méi)有出現(xiàn)這個(gè)問(wèn)題,但評(píng)論中有提及。

有人說(shuō)是backend storage的問(wèn)題,這里是本地存儲(chǔ)鏡像,不應(yīng)該。經(jīng)過(guò)查閱大量資料,并反復(fù)操作驗(yàn)證,是docker-registry版本的問(wèn)題。從v0.10.0開(kāi)始,docker login雖然succeeded,但pull或push的時(shí)候,~/.dockercfg下的用戶登錄信息將不允許通過(guò)http明文傳輸。(如果你愿意可以查看v0.10.0的源碼 registry.go,在分支v0.9.1及以前是沒(méi)有http code 401, docker will not send auth headers over http的)

目前的辦法三個(gè):

  1. 撤退,這就是為什么先說(shuō)明在操作前線查看到這的原因了

  2. 換成v0.9.1及以下版本?,F(xiàn)在都v1.3.1了,我猜你不會(huì)這么做

  3. 修改源碼session.go,去掉相應(yīng)的判斷行,然后git下來(lái)重新安裝。我猜你更不會(huì)這么做

  4. 安裝ssl證書(shū),使用https傳輸。這是明智的選擇,新版本docker也推薦我們這么做,往下看。

3.3 為nginx安裝ssl證書(shū)

首先打開(kāi)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會(huì)分別從/etc/nginx/ssl/nginx.crt和/etc/nginx/ssl/nginx.key讀取ssl證書(shū)和私鑰。如果你自己愿意花錢買一個(gè)ssl證書(shū),那就會(huì)變得非常簡(jiǎn)單,把證書(shū)和私鑰拷貝成上面一樣即可。關(guān)于ssl以及簽署ssl證書(shū),請(qǐng)參考其他文章。

這里我們自簽署一個(gè)ssl證書(shū),把當(dāng)前系統(tǒng)作為(私有)證書(shū)頒發(fā)中心(ca)。

創(chuàng)建存放證書(shū)的目錄

# mkdir /etc/nginx/ssl
確認(rèn)ca的一些配置文件
 
# vi /etc/pki/tls/openssl.cnf
...
[ ca_default ]

dir    = /etc/pki/ca   # where everything is kept
certs   = $dir/certs   # where the issued certs are kept
crl_dir   = $dir/crl    # where the issued crl are kept
database  = $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 certificate
serial   = $dir/serial   # the current serial number
crlnumber  = $dir/crlnumber  # the current crl number
          # must be commented out to leave a v1 crl
crl    = $dir/crl.pem   # the current crl
private_key  = $dir/private/cakey.pem # the private key
randfile  = $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    = cn
countryname_min     = 2
countryname_max     = 2

stateorprovincename    = state or province name (full name)
stateorprovincename_default  = gd
...[ req_distinguished_name ]部分主要是頒證時(shí)一些默認(rèn)的值,可以不動(dòng)

(1) 生成根密鑰

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

為了安全起見(jiàn),修改cakey.pem私鑰文件權(quán)限為600或400,也可以使用子shell生成( umask 077; openssl genrsa -out private/cakey.pem 2048 ),下面不再重復(fù)。

(2) 生成根證書(shū)

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

會(huì)提示輸入一些內(nèi)容,因?yàn)槭撬接械?,所以可以隨便輸入,最好記住能與后面保持一致。上面的自簽證書(shū)cacert.pem應(yīng)該生成在/etc/pki/ca下。

(3) 為我們的nginx web服務(wù)器生成ssl密鑰

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

我們的ca中心與要申請(qǐng)證書(shū)的服務(wù)器是同一個(gè),否則應(yīng)該是在另一臺(tái)需要用到證書(shū)的服務(wù)器上生成。

(4) 為nginx生成證書(shū)簽署請(qǐng)求

 # openssl req -new -key nginx.key -out nginx.csr
...
country name (2 letter code) [au]:cn
state or province name (full name) [some-state]:gd
locality name (eg, city) []:sz
organization name (eg, company) [internet widgits pty ltd]:company
organizational unit name (eg, section) []:it_section
common name (e.g. server fqdn or your name) []:your.domain.com
email address []:

please enter the following 'extra' attributes
to be sent with your certificate request
a challenge password []:
an optional company name []:
...

同樣會(huì)提示輸入一些內(nèi)容,其它隨便,除了commone name一定要是你要授予證書(shū)的服務(wù)器域名或主機(jī)名,challenge password不填。

(5) 私有ca根據(jù)請(qǐng)求來(lái)簽發(fā)證書(shū)

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

上面簽發(fā)過(guò)程其實(shí)默認(rèn)使用了-cert cacert.pem -keyfile cakey.pem,這兩個(gè)文件就是前兩步生成的位于/etc/pki/ca下的根密鑰和根證書(shū)。

到此我們已經(jīng)擁有了建立ssl安全連接所需要的所有文件,并且服務(wù)器的crt和key都位于配置的目錄下,唯有根證書(shū)cacert.pem位置不確定放在centos6下的哪個(gè)地方。

經(jīng)驗(yàn)證以下幾個(gè)位置不行:(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

都會(huì)報(bào)錯(cuò):

# docker login https://registry.domain.com:8000
username (sean): sean
2014/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:sean@registry.domain.com:8000/
curl: (60) peer certificate cannot be authenticated with known ca certificates
more details here: http://curl.haxx.se/docs/sslcerts.html
curl 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) 目前讓根證書(shū)起作用的只發(fā)現(xiàn)一個(gè)辦法: 

# cp /etc/pki/tls/certs/ca-bundle.crt{,.bak} 備份以防出錯(cuò)
# cat /etc/pki/ca/cacert.pem >> /etc/pki/tls/certs/ca-bundle.crt

# curl https://sean:sean@registry.domain.com:8000
"docker-registry server (dev) (v0.8.1)"

cacert.pem根證書(shū)追加到ca-bundle.crt后一定要重啟docker后臺(tái)進(jìn)程才行。

如果docker login依然報(bào)錯(cuò)certificate signed by unknown authority,參考running docker with https,啟動(dòng)docker后臺(tái)進(jìn)程時(shí)指定信任的ca根證書(shū):

 # 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>

上面用“如果”是因?yàn)橐婚_(kāi)始總提示certificate signed by unknown authority,有人說(shuō)將根證書(shū)放在/etc/docker/certs.d下,還有人說(shuō)啟動(dòng)docker daemon收加入--insecure-registry .. 但終究是因?yàn)榘姹静町惒怀晒Α5髞?lái)又奇跡般的不需要--tlscacert就好了。
這個(gè)地方掙扎了很久,重點(diǎn)關(guān)注一下這個(gè)下面幾個(gè)issue:




(7) 最終搞定:

# docker login https://registry.domain.com:8000
username: sean
password: 
email: zhouxiao@domain.com
login succeeded

# curl https://sean:sean@registry.domain.com:8000
"docker-registry server (dev) (v0.8.1)"

# docker push registry.domain.com:8000/centos6:test_priv
the push refers to a repository [registry.domain.com:8000/centos6] (len: 1)
sending image list
pushing 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}

但還有一個(gè)小問(wèn)題沒(méi)解決,雖然已經(jīng)可以正常使用,但每次請(qǐng)求在nginx的error.log中還是會(huì)有[error] 8299#0: *27 no user/password was provided for basic authentication,應(yīng)該是這個(gè)版本docker暫未解決的bug。

3.3 其它問(wèn)題

(1) docker后臺(tái)進(jìn)程意外中斷后,重新docker start <container_id>報(bào)錯(cuò) 

# docker start b36bd796bd3d
error: 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 busy
2014/11/08 15:14:57 error: failed to start one or more containers

經(jīng)分析產(chǎn)生這個(gè)問(wèn)題的原因是做了一個(gè)操作:在docker后臺(tái)進(jìn)程啟動(dòng)的終端,繼續(xù)回車后會(huì)臨時(shí)退出后臺(tái)進(jìn)程的日志輸出,我就在這個(gè)shell下使用yum安裝軟件包,但由于網(wǎng)絡(luò)原因yum卡住不動(dòng),于是我就另起了一個(gè)終端kill了這個(gè)yum進(jìn)程,不知為何會(huì)影響到表面已經(jīng)退出前臺(tái)輸出的docker。解決辦法是umount容器的掛載點(diǎn):(見(jiàn)這里)

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

能想到的另外一個(gè)辦法是,啟動(dòng)docker后臺(tái)進(jìn)程時(shí),重定向輸出docker -d > /dev/null 2>&1(/var/log/docker已自動(dòng)記錄了一份日志)。

(2) 配置完nginx的docker-registry.conf后啟動(dòng)報(bào)錯(cuò)

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

 原因是nginx版本太低,一些配置指令不兼容,使用yum install nginx默認(rèn)安裝了1.0.x,卸載重新下載nginx-1.4.7-1.el6.ngx.x86_64.rpm安裝解決。

(3) 網(wǎng)絡(luò)設(shè)置代理問(wèn)題

pull, push官網(wǎng)的鏡像時(shí)由于gfw的原因需要設(shè)置代理,但不是http_proxy而是http_proxy,對(duì)于docker來(lái)說(shuō)同時(shí)設(shè)置這兩個(gè)值就會(huì)出問(wèn)題,有時(shí)出于安裝軟件包的需要設(shè)置http_proxy,就會(huì)導(dǎo)致沖突。在docker-registry中如果忘記了當(dāng)前哪一個(gè)在起作用,找遍所有問(wèn)題都發(fā)現(xiàn)不了原因,而docker返回給我們的錯(cuò)誤也難以判斷。切記~

to-do
如何刪除docker-registry的里的鏡像

到此,關(guān)于“如何搭建docker內(nèi)網(wǎng)私服”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI