利用阿里云 OSS 搭建私有 Docker 倉庫

jopen 8年前發布 | 37K 次閱讀 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/amd64

Server: 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

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!