前言
Docker不僅是一個強大的服務器部署工具,而且它還有一個官方的Docker Hub registry用於儲存Docker鏡像。上傳鏡像到Docker Hub是免費的,上傳的鏡像文件同時也對公共領域開放,而這可能不是我們想要的。
本文介紹如何配置一個私有的Docker registry,在此上傳的鏡像是私密的,你可以從另一個聯網的主機以安全的方式下載此registry上的鏡像。
本文僅介紹registry的創建,而不討論應用的容器化。有關Docker鏡像創建的操作可參考這篇Docker入門文章。
本文在Ubuntu 14.04上實測通過,在其他Debian類系統上應該也可以通過。使用的Docker Registry版本為2.0版。
Docker基本概念
如果你此前尚未用過Docker,那么最好先花幾分鍾時間了解一下它的基本概念。如果你已經使用過Docker,只想了解建立私有registry部分的內容,則可跳過本小節。
Docker入門者可參閱這篇Docker Cheat Sheet。
Docker的核心理念是應用及其依賴項與其運行環境(操作系統)的分離,這種分離通過容器(containers)和鏡像(images)來實現。一個Docker鏡像本質上來說就是一個文件系統的模板,運行一個Docker鏡像就是在你的系統上的一個Docker容器中運行該文件系統的一個實例。默認來說,該容器是不會接觸到最初的那個鏡像或者Docker運行環境所處的宿主機上的文件系統:該容器是完全獨立的環境。
在容器內部操作進行的變更直接在容器中預存,而不會造成初始鏡像的變更;要保存這些變更,需要通過docker commit指令將變更提交給指定的Docker鏡像。也就是說,從一個舊的容器,你可以不斷的生成新的容器,而舊的那個容器(鏡像)永遠也不會因為意外而被搞砸。該模式對於Git用戶而言應該非常眼熟,這相當於創建新的分支(git branch相當於Docker image),運行一個鏡像相當於做一次git checkout。
運用同樣的類比,一個私有Docker registry就相當於一個私有的git倉庫。
准備工作
完成本教程需要如下准備工作:
兩台Ubuntu 14.04的雲主機,一台作為私有Docker registry服務器,一台作為Docker客戶端。
兩台服務器上都建立具有sudo權限的非root用戶(用戶建立教程可參考這篇文章)。
兩台服務器上都安裝Docker以及Docker Compose(安裝教程見此)。
為私有Docker registry服務器配置好可供客戶端訪問的域名。
步驟1:安全加固
針對Docker Registry的安全加固,建議使用Docker Compose。如此,我們可以在一個容器內運行Docker Registry,而與外部的通訊安全則交給另一個容器內的Nginx來處理。我們在准備工作中應該已經安裝過Docker Compose。
用Nginx來處理通訊安全,則需要將可訪問私有registry的用戶名和密碼的列表保存到一個文件里以供Nginx讀取。我們將安裝apache2-utils軟件包,該軟件包下的htpasswd可以很方便的生成一個Nginx可讀的密碼哈希:
sudo apt-get -y install apache2-utils
步驟2:安裝配置Docker Registry
如果你只需要管理一兩個Docker容器,那么Docker命令行工具就足夠好了。然而,大部分在容器內運行的應用並非是獨立運作的,他們需要成組配合才能運行。比如,大部分Web應用都至少需要一個Web服務器用於托管應用代碼、一個服務器用於運行PHP/Ruby on Rails等解釋腳本語言、一台數據庫服務器(如MySQL)。
Docker Compose可以讓我們為每一個容器用一個.yml配置文件,該文件不僅可以指定容器的配置項,還可以寫入有關該容器如何對外通訊的信息。docker-compose命令行工具可以對應用的各個組件下達指令。
Docker registry本身也是一個由多個組件組成的應用,因此我們將使用Docker Compose對其進行配置管理。
最簡單的registry配置就是其存儲數據的位置。讓我們先來創建一個最基本的Docker Compose YAML文件。
首先,創建一個目錄,用於儲存本教程將要用到的一些文件:
mkdir ~/docker-registry && cd $_
mkdir data
在該目錄下創建一個docker-compose.yml文件:
nano docker-compose.yml
將如下內容復制粘貼到該文件中:
registry:
image: registry:2
ports:
- 127.0.0.1:5000:5000
environment:
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
volumes:
- ./data:/data
注意這部分內容:environment: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data為Docker registry容器設置了一個環境變量路徑/data,如此,Docker registry在啟動時就會檢查這個環境變量,從而將其數據保存到/data路徑下。
最后的volumes: - ./data:/data這一段的意思是,容器內的/data路徑應該映射到宿主機的./data路徑,也就是說Docker registry的數據都會保存到宿主機的~/docker-registry/data目錄下。
現在啟動Docker Compose:
cd ~/docker-registry
docker-compose up
輸入該命令后,你會看到一系列下載進度條,這些是Docker在從官方Registry下載Docker registry鏡像文件的下載進度。如果一切順利,下載應該在一兩分鍾內完成,最終呈現的輸出應該是這樣的:
registry_1 | time="2015-10-18T23:45:58Z" level=warning msg="No HTTP secret provided - generated random secret. This may cause problems with uploads if multiple registries are behind a load-balancer. To provide a shared secret, fill in http.secret in the configuration file or set the REGISTRY_HTTP_SECRET environment variable." instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
registry_1 | time="2015-10-18T23:45:58Z" level=info msg="redis not configured" instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
registry_1 | time="2015-10-18T23:45:58Z" level=info msg="using inmemory blob descriptor cache" instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
registry_1 | time="2015-10-18T23:45:58Z" level=info msg="listening on [::]:5000" instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
registry_1 | time="2015-10-18T23:45:58Z" level=info msg="Starting upload purge in 1m0s" instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
里面有一條No HTTP secret provided的警告信息,不用在意它。
至此,你的Docker registry已經在運行,監聽端口為5000(這個端口可以在docker-compose.yml文件中的ports:部分設置)。不過這個registry現在還用處不大:一方面它需要手動啟動,另一方面它還沒設置任何身份驗證機制所以並不安全。
默認狀態下,Docker Compose會一直等待你輸入指令。現在我們直接CTRL-C將其關閉退出。
步驟3:設置Nginx容器
現在來解決安全認證的問題。首先我們需要一個Nginx容器,再把它跟剛才的Docker registry容器連接起來。
創建一個新目錄用於保存Nginx配置項:
mkdir ~/docker-registry/nginx
打開剛才的docker-compose.yml文件:
nano docker-compose.yml
將下面的內容復制粘貼到文件開頭處:
nginx:
image: "nginx:1.9"
ports:
- 5043:443
links:
- registry:registry
volumes:
- ./nginx/:/etc/nginx/conf.d:ro
這將基於官方Nginx鏡像創建一個新的Docker容器。注意這里的links部分,這個功能可以自動建立兩個容器之間的連接:當Nginx容器啟動時,它將能夠直接使用registry這個主機名訪問registry容器(無論該容器的IP地址為何。其背后的機制其實是在nginx容器里面的/etc/hosts文件把registry容器的IP自動填寫進去)。
volumes:部分跟上面一樣,是容器內外路徑的映射關系。末尾的:ro意思是只讀,即該Nginx容器對宿主機文件系統只有只讀權限。
到目前為止,完整的docker-compose.yml文件應該是這樣的:
nginx:
image: "nginx:1.9"
ports:
- 5043:443
links:
- registry:registry
volumes:
- ./nginx/:/etc/nginx/conf.d
registry:
image: registry:2
ports:
- 127.0.0.1:5000:5000
environment:
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
volumes:
- ./data:/data
現在如果再次運行docker-compose up,將會啟動兩個容器:一個Docker registry和一個Nginx。不過我們需要先配置好Nginx。創建一個新的Nginx配置文件registry.conf:
nano ~/docker-registry/nginx/registry.conf
將如下內容復制粘貼進去:
upstream docker-registry {
server registry:5000;
}
server {
listen 443;
server_name myregistrydomain.com;
# SSL
# ssl on;
# ssl_certificate /etc/nginx/conf.d/domain.crt;
# ssl_certificate_key /etc/nginx/conf.d/domain.key;
# disable any limits to avoid HTTP 413 for large image uploads
client_max_body_size 0;
# required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
chunked_transfer_encoding on;
location /v2/ {
# Do not allow connections from docker 1.5 and earlier
# docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents
if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
return 404;
}
# To add basic authentication to v2 use auth_basic setting plus add_header
# auth_basic "registry.localhost";
# auth_basic_user_file /etc/nginx/conf.d/registry.password;
# add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;
proxy_pass http://docker-registry;
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;
}
}
保存退出。現在可以啟動Docker Compose了:
docker-compose up
Nginx在啟動時沒有輸出信息,不過我們可以用curl來測試一下它是不是已經成功啟動並連接至registry。首先用curl發送HTTP請求給registry:
curl http://localhost:5000/v2/
你應該能看到返回的結果——一個空json對象:
{}
現在再給Nginx端口發送HTTP請求:
curl http://localhost:5043/v2/
你應該看到同樣的返回結果:
{}
如果一切順利,在docker-compose的終端能看到如下的輸出內容:
registry_1 | time="2015-08-11T10:24:53.746529894Z" level=debug msg="authorizing request" environment=development http.request.host="localhost:5043" http.request.id=55c3e2a6-4f34-4b0b-bc57-11c814b4f4d3 http.request.method=GET http.request.remoteaddr=172.17.42.1 http.request.uri="/v2/" http.request.useragent="curl/7.35.0" instance.id=55634dfc-c9e0-4ec9-9872-6f4930c17759 service=registry version=v2.0.1
registry_1 | time="2015-08-11T10:24:53.747650205Z" level=info msg="response completed" environment=development http.request.host="localhost:5043" http.request.id=55c3e2a6-4f34-4b0b-bc57-11c814b4f4d3 http.request.method=GET http.request.remoteaddr=172.17.42.1 http.request.uri="/v2/" http.request.useragent="curl/7.35.0" http.response.contenttype="application/json; charset=utf-8" http.response.duration=8.143193ms http.response.status=200 http.response.written=2 instance.id=55634dfc-c9e0-4ec9-9872-6f4930c17759 service=registry version=v2.0.1
registry_1 | 172.17.0.21 - - [11/Aug/2015:10:24:53 +0000] "GET /v2/ HTTP/1.0" 200 2 "" "curl/7.35.0"
nginx_1 | 172.17.42.1 - - [11/Aug/2015:10:24:53 +0000] "GET /v2/ HTTP/1.1" 200 2 "-" "curl/7.35.0" "-"
如果你看到registry_這樣的前綴(后面的數字不一定是1),則說明一切正常,Nginx已經成功建立了到Docker registry的代理。
CTRL-C退出,准備進行下一步操作。
步驟4:設置驗證信息
現在我們需要讓Nginx驗證訪問Docker registry的用戶權限。首先我們需要用htpasswd工具創建一個Apache格式的驗證文件(Nginx也可以識別該文件):
cd ~/docker-registry/nginx
htpasswd -c registry.password USERNAME
其中的USERNAME是你自己指定的用戶名。指令輸入后,命令行會請求為該用戶建立一個密碼。
如果以后要添加新用戶,還是一樣使用htpasswd工具,只是不用再輸入-c選項了(c是新建的意思):
htpasswd registry.password USERNAME
現在我們有了一個registry.password文件,里面保存了可以訪問registry的用戶名列表。這個文件是可以隨時查看編輯的。
接下來需要讓Nginx把這個文件用起來。還是打開~/docker-registry/nginx/registry.conf文件:
nano ~/docker-registry/nginx/registry.conf
找到下面這幾行內容:
# To add basic authentication to v2 use auth_basic setting plus add_header
# auth_basic "registry.localhost";
# auth_basic_user_file /etc/nginx/conf.d/registry.password;
# add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;
將auth_basic和add_header這兩行前面的井號去掉:
# To add basic authentication to v2 use auth_basic setting plus add_header
auth_basic "registry.localhost";
auth_basic_user_file /etc/nginx/conf.d/registry.password;
add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;
這樣就啟動了HTTP驗證功能。保存退出,來把容器們啟動起來看看:
cd ~/docker-registry
docker-compose up
還是用curl來給Nginx發送請求:
curl http://localhost:5043/v2/
這次的返回結果是一個驗證失敗的頁面:
<html>
<head><title>401 Authorization Required</title></head>
<body bgcolor="white">
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx/1.9.7</center>
</body>
</html>
現在加上用戶名和密碼,再用curl發送一次請求:
curl http://USERNAME:PASSWORD@localhost:5043/v2/
這次,你應該能看到之前的返回結果——空json對象{}。在docker-compose的終端也能夠看到registry_部分的內容。
CTRL-C退出,准備進行下一步。
步驟5:設置SSL
雖然已經有了基本的HTTP驗證,但現在還是不夠安全,因為連接是未加密的。我們需要把SSL啟用起來。還是打開剛才的Nginx配置文件:
nano ~/docker-registry/nginx/registry.conf
找到如下內容:
server {
listen 443;
server_name myregistrydomain.com;
# SSL
# ssl on;
# ssl_certificate /etc/nginx/conf.d/domain.crt;
# ssl_certificate_key /etc/nginx/conf.d/domain.key;
把SSL以下的三行前面的井號刪掉。不要忘了把server_name部分的值改成你的服務器域名:
server {
listen 443;
server_name myregistrydomain.com;
# SSL
ssl on;
ssl_certificate /etc/nginx/conf.d/domain.crt;
ssl_certificate_key /etc/nginx/conf.d/domain.key;
保存退出。Nginx將使用/etc/nginx/conf.d/domain.crt證書以及/etc/nginx/conf.d/domain.key密鑰來提供SSL服務。根據之前的配置,容器內的/etc/nginx/conf.d/路徑是映射到宿主機的~/docker-registry/nginx/路徑下,所以我們需要把證書文件復制到這里。你可以購買證書,也可以獲取一個免費的SSL證書。或者,你也可以使用自簽名的SSL證書。
自簽名的SSL證書
目前為止,Docker還無法正式支持自簽名的SSL證書,所以這個配置起來要麻煩一些——我們需要將宿主機設置為證書的頒發機構。
到~/docker-registry/nginx目錄下,創建一個新的root key:
cd ~/docker-registry/nginx
openssl genrsa -out devdockerCA.key 2048
生成一個root證書(需要填寫國家省市信息之類的,這些可以隨便填):
openssl req -x509 -new -nodes -key devdockerCA.key -days 10000 -out devdockerCA.crt
然后,生成key(這個密鑰就是上面需要用到的ssl_certificate_key):
openssl genrsa -out domain.key 2048
然后,我們需要進行一個證書簽名的請求。
輸入如下命令。輸入之后,OpenSSL會向你提出幾個問題。其他問題怎么回答都好,不過關於"Common Name"這一項,務必要填寫服務器的域名或IP:
openssl req -new -key domain.key -out dev-docker-registry.com.csr
比如,如果你的Docker registry使用的域名是www.ilovedocker.com,則需要這樣填寫:
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:www.ilovedocker.com
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
A challenge password []:這里不要填。
然后,我們要給這個證書請求做簽名:
openssl x509 -req -in dev-docker-registry.com.csr -CA devdockerCA.crt -CAkey devdockerCA.key -CAcreateserial -out domain.crt -days 10000
因為我們剛才生成的這些證書沒有被任何權威機構(比如VeriSign)驗證過,因此我們需要用另外的方法告訴所有使用這個Docker registry的客戶端說,這個Docker registry使用的證書是合法的。這個方法就是,在每個Docker客戶端上做如下設置(需要把剛才生成的devdockerCA.crt復制過去):
sudo mkdir /usr/local/share/ca-certificates/docker-dev-cert
sudo cp devdockerCA.crt /usr/local/share/ca-certificates/docker-dev-cert
sudo update-ca-certificates
重啟Docker守護進程以使該證書生效:
sudo service docker restart
詳細配置過程見本文步驟9。上述指令在本機執行可直接生效。
步驟6:測試SSL
現在啟動容器:
cd ~/docker-registry
docker-compose up
再做一次curl,但是用https(這里輸入的域名或IP必須與剛才在證書生成過程中填寫的Common Name部分完全一致):
curl https://USERNAME:PASSWORD@[YOUR-DOMAIN]:5043/v2/
如果剛才用了自簽名證書,你會看到如下問題報告:
curl: (60) SSL certificate problem: self signed certificate
為curl命令加上-k選項可以跳過該驗證:
curl -k https://USERNAME:PASSWORD@[YOUR-DOMAIN]:5043/v2/
如此,應該可以得到空json對象{}的返回結果。docker-compose的終端窗口那邊也會輸出registry_部分內容。否則的話,則需要回去重新檢查SSL設置的步驟。
至此,如果你的防火牆配置允許來自外部的請求訪問5043端口,則你應該可以使用自己的用戶名和密碼通過docker login https://<YOURDOMAIN>登陸到該Docker registry上了。
步驟7:將SSL端口設置為443
443是標准的SSL端口,所以我們要把之前設置的5043改成443。不過在Linux上,1024以下的端口都是“特權”端口,所以docker-compose容器必須以root權限運行才能使用該端口。
打開docker-compose.yml進行編輯:
nano ~/docker-registry/docker-compose.yml
在Nginx部分的ports:段落,原本的內容是- 5043:443,即把宿主機的5043端口映射到Nginx容器的443端口。我們要把它改成- 443:443:
nginx:
image: "nginx:1.9"
ports:
- 443:443
links:
- registry:registry
volumes:
- ./nginx/:/etc/nginx/conf.d:ro
registry:
image: registry:2
ports:
- 127.0.0.1:5000:5000
environment:
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
volumes:
- ./data:/data
CTRL-C退出之前運行的docker-compose(如果之前已經退出就無需進行此操作),然后以sudo權限再次啟動:
sudo docker-compose up
現在docker-compose已經啟動,再次使用curl命令來做一次測試。這次我們在URL中不再指定端口:
curl https://<YOURUSERNAME>:<YOURPASSWORD>@YOUR-DOMAIN/v2/
檢查返回的結果是否為{},docker-compose終端窗口的輸出是否包含registry_。在外部的另一台機器上重復本操作,以確保Docker registry可以從外部訪問。
如果一切正常,CTRL-C退出,准備進行下一步。
步驟8:將Docker Registry啟動為服務
接下來我們創建一個Upstart腳本以使Docker registry在每次系統啟動時一起啟動。
首先我們需要移除之前已經生成的容器,好把整個Docker registry目錄移動到系統通用目錄下,再將其權限更改為root權限:
cd ~/docker-registry
docker-compose rm # 移除現有的容器
sudo mv ~/docker-registry /docker-registry
sudo chown -R root: /docker-registry
然后創建一個Upstart腳本:
sudo nano /etc/init/docker-registry.conf
將以下內容復制粘貼到文件中(該腳本內容有一些復雜,其說明可參考這篇博文。有關Upstart的用法可參考這篇教程。):
description "Docker Registry"
start on runlevel [2345]
stop on runlevel [016]
respawn
respawn limit 10 5
chdir /docker-registry
exec /usr/local/bin/docker-compose up
現在用如下命令測試一下該Upstart腳本:
sudo service docker-registry start
返回的結果應該是這樣的:
docker-registry start/running, process 25303
使用如下命令檢查Docker服務是否已經在運行:
docker ps
返回的結果應該是這樣的(其中包含dockerregistry_的項目):
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d4b6fef0b4d1 nginx:1.9 "nginx -g 'daemon of 2 minutes ago Up 2 minutes 80/tcp, 0.0.0.0:443->443/tcp dockerregistry_nginx_1
77668352bd39 registry:2 "registry cmd/regist 2 minutes ago Up 2 minutes 127.0.0.1:5000->5000/tcp dockerregistry_registry_1
Upstart會把docker-compose命令的輸出都錄入到/var/log/upstart/docker-registry.log日志文件中。用tail命令檢查一下這個日志文件(需要使用sudo,因為upstart日志是以root用戶寫入的):
sudo tail -f /var/log/upstart/docker-registry.log
里面應該能看到包含registry_的條目。再從本機的新終端窗口或另一台機器curl到registry服務器上:
curl https://<YOUR_USERNAME>:<YOURPASSWORD>@[YOUR-DOMAIN]/v2/
檢查返回的結果是否為{}。日志文件中應該能看到跟之前一樣的信息:
registry_1 | time="2015-08-12T08:01:12.241887501Z" level=debug msg="authorizing request" environment=development http.request.host=docker.meatflavoredbeer.com http.request.id=e8d69e16-9448-4c48-afd8-57b1f1302742 http.request.method=GET http.request.remoteaddr=106.1.247.4 http.request.uri="/v2/" http.request.useragent="curl/7.37.1" instance.id=14d4727b-fda1-463f-8d0e-181f4c70cb17 service=registry version=v2.0.1
registry_1 | time="2015-08-12T08:01:12.242206499Z" level=info msg="response completed" environment=development http.request.host=docker.meatflavoredbeer.com http.request.id=e8d69e16-9448-4c48-afd8-57b1f1302742 http.request.method=GET http.request.remoteaddr=106.1.247.4 http.request.uri="/v2/" http.request.useragent="curl/7.37.1" http.response.contenttype="application/json; charset=utf-8" http.response.duration=3.359883ms http.response.status=200 http.response.written=2 instance.id=14d4727b-fda1-463f-8d0e-181f4c70cb17 service=registry version=v2.0.1
registry_1 | 172.17.0.4 - - [12/Aug/2015:08:01:12 +0000] "GET /v2/ HTTP/1.0" 200 2 "" "curl/7.37.1"
nginx_1 | 106.1.247.4 - nik [12/Aug/2015:08:01:12 +0000] "GET /v2/ HTTP/1.1" 200 2 "-" "curl/7.37.1" "-"
步驟9:配置需要訪問Docker Registry的客戶端
如步驟5所述,對於使用自簽名SSL證書的情況,所有需要訪問該Docker registry的客戶端都需要添加我們創建的證書。我們需要把~/docker-registry/nginx/devdockerCA.crt這個文件復制到客戶端機器上。
首先在服務器上查看該證書文件:
sudo cat /docker-registry/nginx/devdockerCA.crt
文件內容差不多是這樣的形式:
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJANiXy7fHSPrmMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTQwOTIxMDYwODE2WhcNNDIwMjA2MDYwODE2WjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAuK4kNFaY3k/0RdKRK1XLj9+IrpR7WW5lrNaFB0OIiItHV9FjyuSWK2mj
ObR1IWJNrVSqWvfZ/CLGay6Lp9DJvBbpT68dhuS5xbVw3bs3ghB24TntDYhHMAc8
GWor/ZQTzjccHUd1SJxt5mGXalNHUharkLd8mv4fAb7Mh/7AFP32W4X+scPE2bVH
OJ1qH8ACo7pSVl1Ohcri6sMp01GoELyykpXu5azhuCnfXLRyuOvQb7llV5WyKhq+
SjcE3c2C+hCCC5g6IzRcMEg336Ktn5su+kK6c0hoD0PR/W0PtwgH4XlNdpVFqMST
vthEG+Hv6xVGGH+nTszN7F9ugVMxewIDAQABo1AwTjAdBgNVHQ4EFgQULek+WVyK
dJk3JIHoI4iVi0FPtdwwHwYDVR0jBBgwFoAULek+WVyKdJk3JIHoI4iVi0FPtdww
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkignESZcgr4dBmVZqDwh
YsrKeWSkj+5p9eW5hCHJ5Eg2X8oGTgItuLaLfyFWPS3MYWWMzggxgKMOQM+9o3+k
oH5sUmraNzI3TmAtkqd/8isXzBUV661BbSV0obAgF/ul5v3Tl5uBbCXObC+NUikM
O0C3fDmmeK799AM/hP5CTDehNaFXABGoVRMSlGYe8hZqap/Jm6AaKThV4g6n4F7M
u5wYtI9YDMsxeVW6OP9ZfvpGZW/n/88MSFjMlBjFfFsorfRd6P5WADhdfA6CBECG
LP83r7/MhqO06EOpsv4n2CJ3yoyqIr1L1+6C7Erl2em/jfOb/24y63dj/ATytt2H
6g==
-----END CERTIFICATE-----
把證書內容復制到剪貼板上。
登陸到客戶端機器,創建證書目錄:
sudo mkdir /usr/local/share/ca-certificates/docker-dev-cert
再創建證書文件,使用同樣的文件名devdockerCA.crt:
sudo nano /usr/local/share/ca-certificates/docker-dev-cert/devdockerCA.crt
將剛才復制到剪貼板上的內容粘貼進來。保存退出。再使用cat查看一下新創建的文件,檢查內容是否正確:
cat /usr/local/share/ca-certificates/docker-dev-cert/devdockerCA.crt
確認無誤后,更新證書信息:
sudo update-ca-certificates
返回的結果應該包含1 added信息:
Updating certificates in /etc/ssl/certs... 1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d....done.
重啟Docker以重新加載系統CA證書列表:
sudo service docker restart
現在可以使用如下指令登入Docker registry了:
docker login https://YOUR-DOMAIN
服務器會要求你輸入用戶名、密碼和Email。用戶名和密碼就是剛才在服務器上創建的,Email可以隨便填:
Username: USERNAME
Password: PASSWORD
Email:
Account created. Please see the documentation of the registry http://localhost:5000/v1/ for instructions how to activate it.
如果輸入的信息無誤,應該可以看到登陸成功的信息:
Login Succeeded
步驟10:將本機鏡像發布到Docker Registry
我們先在客戶端上創建一個簡單的鏡像(基於Docker Hub上的ubuntu鏡像。如果本機上已經有鏡像那就可以省去這一步了):
docker run -t -i ubuntu /bin/bash
該指令會下載ubuntu鏡像並運行其中的bash以等待我們給該容器輸入指令,這可能需要一段時間。等等待輸入的指令出現之后,我們來創建一個文件SUCCESS:
touch /SUCCESS
現在可以退出容器了:
exit
將變更后的鏡像提交為test-image:
docker commit $(docker ps -lq) test-image
根據我們上面的操作,這個test-image鏡像與官方ubuntu鏡像相比,只是添加了一個空文件SUCCESS。
現在我們把這個測試鏡像推送到registry。
登陸到registry服務器:
docker login https://YOUR-DOMAIN
輸入用戶名和密碼:
Username: USERNAME
Password: PASSWORD
Email:
Account created. Please see the documentation of the registry http://localhost:5000/v1/ for instructions how to activate it.
現在可以推送剛才的鏡像。根據Docker的設計,我們推送之前,需要給它加一個tag用於標注registry的位置:
docker tag test-image [YOUR-DOMAIN]/test-image
這里需要注意的是,tag中的域名不需要https://,只需要域名、端口、加上鏡像名稱即可。
現在可以推送了:
docker push [YOUR-DOMAIN]/test-image
推送需要一段時間,完成后應該能看到如下內容:
latest: digest: sha256:5ea1cfb425544011a3198757f9c6b283fa209a928caabe56063f85f3402363b4 size: 8008
步驟11:從Docker Registry拉取鏡像
現在測試從另一台機器拉取該鏡像(我們也可以直接在registry服務器上進行本測試)。
登陸到registry服務器:
docker login https://[YOUR-DOMAIN]
使用剛才創建的tag拉取鏡像:
docker pull [YOUR-DOMAIN]/test-image
Docker會下載該鏡像。下載完成后,輸入如下指令運行鏡像以進入到里面:
docker run -t -i [YOUR-DOMAIN]/test-image /bin/bash
看看里面是不是有剛才創建的文件:
ls
應該可以看到SUCCESS文件出現在列表中:
SUCCESS bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
總結
至此,我們已經成功創建了一個私有Docker Registry服務器,並且完成了鏡像的推送和拉取。現在可以盡情的玩弄你的Docker啦!
轉載:http://blog.csdn.net/zstack_org/article/details/53301211?locationNum=12&fps=1