利用阿里云 OSS 搭建私有 Docker 倉庫
最近開始研究 Docker 的應用,于是打算 搭建一個私有的 Docker 倉庫,并使用阿里云的 OSS 作為存儲引擎 。從網上搜索到的資料大都是比較舊的,新版本的 Registry 服務與舊版本的差別比較大,瞎折騰了一天,踩坑無數。突然有感, 網上的過時資料(或者說得不清不楚的)真是坑死人不償命 ,還是得把這兩天摸索出來的門道記錄下來,一是好讓自己過一段時間后再部署 Docker 倉庫時不用重踩一次坑,二來也順便給后來者提個醒。
系統環境
客戶端 docker 版本:
docker version Client: Version: 1.9.1 API version: 1.21 Go version: go1.4.3 Git commit: a34a1d5 Built: Fri Nov 20 17:56:04 UTC 2015 OS/Arch: darwin/amd64Server: Version: 1.9.1 API version: 1.21 Go version: go1.4.3 Git commit: a34a1d5 Built: Fri Nov 20 17:56:04 UTC 2015 OS/Arch: linux/amd64</pre>
服務器端 docker 版本:
Boot2Docker version 1.9.1, build master : cef800b - Fri Nov 20 19:33:59 UTC 2015 Docker version 1.9.1, build a34a1d5客戶端 docker-compose 版本:
docker-compose version 1.5.2, build 7240ff3 docker-py version: 1.5.0 CPython version: 2.7.9 OpenSSL version: OpenSSL 1.0.1j 15 Oct 2014如果系統沒有 docker-compose 命令,可以執行以下命令安裝:
$ curl -L https://github.com/docker/compose/releases/download/1.5.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose $ chmod +x /usr/local/bin/docker-compose啟動 Registry 服務
為了發揮 Docker 容器技術的優勢,我們直接使用 Docker 鏡像來部署服務。
首先在 服務器端 新建工作目錄并進入該目錄:
$ mkdir my_registry && cd my_registry在當前目錄下新建文件 docker-compose.yml :
registry: restart: always image: "registry:2" ports:- 127.0.0.1:5000:5000
volumes:
- ./auth:/auth - ./data:/var/lib/registry
environment:
- REGISTRY_AUTH=htpasswd - REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm - REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd</pre>
在啟動 Registry 服務時,需要用到以下兩個目錄:
- auth 目錄用于存放 docker login 時的賬號和密碼
- data 目錄用于存放 docker push 時上傳上來的文件
執行以下命令新建這兩個目錄:
$ mkdir auth && mkdir data
接著,創建一個測試賬號(用戶名: test ,密碼: 123456 )并保存到 auth/htpasswd 中:
$ htpasswd -Bbn test 123456 > auth/htpasswd
現在我們來啟動 Registry 服務:
$ docker-compose up -d
由于本地沒有名為 registry:2 的鏡像,控制臺可能會打印出如下信息然后暫停一陣:
Pulling registry (registry:2)...
稍等一兩分鐘,可以看到控制臺打印出如下信息則說明已經啟動成功了:
Creating dockertest_registry_1 Attaching to dockertest_registry_1 registry_1 | time="2016-01-13T21:57:14Z" 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." go.version=go1.5.2 instance.id=25aa4d1d-0510-4cb6-9006-1083bff5fc15 version=v2.2.1 registry_1 | time="2016-01-13T21:57:14Z" level=info msg="redis not configured" go.version=go1.5.2 instance.id=25aa4d1d-0510-4cb6-9006-1083bff5fc15 version=v2.2.1 registry_1 | time="2016-01-13T21:57:14Z" level=info msg="using inmemory blob descriptor cache" go.version=go1.5.2 instance.id=25aa4d1d-0510-4cb6-9006-1083bff5fc15 version=v2.2.1 registry_1 | time="2016-01-13T21:57:14Z" level=info msg="Starting upload purge in 11m0s" go.version=go1.5.2 instance.id=25aa4d1d-0510-4cb6-9006-1083bff5fc15 version=v2.2.1 registry_1 | time="2016-01-13T21:57:14Z" level=info msg="listening on [::]:5000" go.version=go1.5.2 instance.id=25aa4d1d-0510-4cb6-9006-1083bff5fc15 version=v2.2.1
現在再打開一個命令行窗口,并進入 my_registry 目錄。
執行以下命令創建一個新鏡像:
$ docker tag registry:2 127.0.0.1:5000/test/registry
說明:鏡像名為 127.0.0.1:5000/test/registry ,其中 127.0.0.1:5000 表示服務器地址, test/registry 表示鏡像名。
上傳之前要先登錄:
$ docker login 127.0.0.1:5000
說明:按提示輸入上文創建的用戶名和密碼,郵箱可以不用填寫。
登陸成功后,執行以下命令即可上傳:
$ docker push 127.0.0.1:5000/test/registry
配置阿里云 OSS
首先在剛才執行 docker-compose up 的命令行窗口中按 CTRL + C 退出服務。
將文件 docker-compose.yml 改為以下內容:
registry: restart: always image: "registry:2" ports:- 127.0.0.1:5000:5000
volumes:
- ./auth:/auth
environment:
- REGISTRY_AUTH=htpasswd - REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm - REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd - REGISTRY_STORAGE=oss - REGISTRY_STORAGE_OSS_ACCESSKEYID=you_oss_accesskey_id - REGISTRY_STORAGE_OSS_ACCESSKEYSECRET=you_oss_accesskey_secret - REGISTRY_STORAGE_OSS_REGION=you_oss_region - REGISTRY_STORAGE_OSS_BUCKET=you_oss_bucket - REGISTRY_STORAGE_OSS_ENDPOINT=you_oss_bucket.you_oss_region.aliyuncs.com</pre>
說明:由于使用阿里云 OSS 作為存儲引擎,所以不需要再將文件存儲到本地,因此將 volumes 中的 data 目錄配置去掉; environment 新增了 REGISTRY_STORAGE 系列的環境變量配置,需要將該部分的值替換為對應的 accesskey_id 、 accesskey_secret 、 region 、 bucket 和 endpoint 等信息。
刪除 data 目錄并重新啟動服務:
$ rm -Rf data && docker-compose up再執行剛才的命令上傳鏡像:
$ docker push 127.0.0.1:5000/test/registry可以感覺到這次的上傳速度沒有第一次的快,因為它還需要上傳到阿里云 OSS。待上傳完畢,可以打開阿里云 OSS 的控制臺界面檢查文件是否被正確上傳上去了。
配置 SSL 證書
如果我們要在客戶端(不是在服務器端測試) pull 或 push 鏡像時, docker 使用的是 https 協議,因此會報 unable to ping registry endpoint 錯誤:
The push refers to a repository [registry.example.com:5000/test] (len: 1) unable to ping registry endpoint https://registry.example.com:5000/v0/ v2 ping attempt failed with error: Get https://registry.example.com:5000/v2/: dial tcp registry.example.com:5000: i/o timeout v1 ping attempt failed with error: Get https://registry.example.com:5000/v1/_ping: dial tcp 199.99.99.9:9000: i/o timeout所以必須要配置 SSL 證書。
首先需要準備證書文件,分別保存到 auth/domain.crt 和 auth/domain.key 中。
新建 Nginx 的配置文件 auth/nginx.conf :
upstream docker-registry { server registry:5000; }Set a variable to help us decide if we need to add the
'Docker-Distribution-Api-Version' header.
The registry always sets this header.
In the case of nginx performing auth, the header will be unset
since nginx is auth-ing before proxying.
map $upstream_http_docker_distribution_api_version $docker_distribution_api_version { 'registry/2.0' ''; default registry/2.0; }
server { listen 443 ssl; server_name myregistrydomain.com;
SSL
ssl_certificate /etc/nginx/conf.d/domain.crt; ssl_certificate_key /etc/nginx/conf.d/domain.key;
Recommendations from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
ssl_protocols TLSv1.1 TLSv1.2; ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH'; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m;
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. auth_basic "Registry realm"; auth_basic_user_file /etc/nginx/conf.d/nginx.htpasswd; ## If $docker_distribution_api_version is empty, the header will not be added. ## See the map directive above where this variable is defined. add_header 'Docker-Distribution-Api-Version' $docker_distribution_api_version 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;
} }</pre>
將文件 docker-compose.yml 改為如下內容:
nginx: image: "nginx:1.9" ports:- 443:443
links:
- registry:registry
volumes:
- ./auth/:/etc/nginx/conf.d
registry: restart: always image: "registry:2" ports:
- 127.0.0.1:5000:5000
environment:
- REGISTRY_STORAGE=oss - REGISTRY_STORAGE_OSS_ACCESSKEYID=you_oss_accesskey_id - REGISTRY_STORAGE_OSS_ACCESSKEYSECRET=you_oss_accesskey_secret - REGISTRY_STORAGE_OSS_REGION=you_oss_region - REGISTRY_STORAGE_OSS_BUCKET=you_oss_bucket - REGISTRY_STORAGE_OSS_ENDPOINT=you_oss_bucket.you_oss_region.aliyuncs.com</pre>
說明:刪除 registry 項目的 environment 中 REGISTRY_AUTH 開頭的變量以及 volumes 項,因為 auth 認證已經在 Nginx 中配置了。
執行以下命令啟動服務:
$ docker-compose up說明:如果本地不存在名為 nginx:1.9 的鏡像,控制臺可能會打印出 Pulling nginx (nginx:1.9)... 并先下載該鏡像。
假設剛才配置的證書域名為 docker.registry.ucdok.com ,現在我們 在客戶端執行以下命令 登錄:
$ docker login docker.registry.ucdok.com生成新的鏡像:
$ docker pull ubuntu $ docker tag ubuntu docker.registry.ucdok.com/test/ubuntu上傳新的鏡像:
$ docker push docker.registry.ucdok.com/test/ubuntu其他問題
增加用戶
可以執行 htpasswd 命令來創建,并將其保存到 auth/htpasswd 文件中:
$ htpasswd -Bbn username password >> auth/htpasswd在后臺啟動服務
啟動服務時增加 -d 參數:
$ docker-compose up -d停止后臺服務
在 docker-compose.yml 文件所在目錄執行以下命令:
$ docker-compose stop相關鏈接
</article>來自: http://morning.work/page/2016-01/deploying-your-own-private-docker-registry.html