架設 Docker Registry v2

我的架設方式與官方文件不太一樣,所以踩了不少雷。

官方文件傾向把 nginx 與 docker-registry 都用 Docker container 的方式連接 (link) 部署,而我的方式與層次是:

  1. AWS ELB
  2. Nginx on EC2 Host OS
  3. Dockerized  docker-registry (registry:2)

因為我想要閃掉 SSL/TLS 的設定,還有惱人的 private key passphrase,所以讓現成已經掛好了憑證的 ELB 充當 SSL/TLS termination proxy。在 ELB 後面的 nginx 與 docker-registry 就不用煩惱憑證的設定問題。

Nginx 主要是負責提供 HTTP basic access authentication,在 docker-registry 前提供一層帳密安全關卡,由於我個人實在是很討厭使用 link,所以把它放在 host 裡。設定檔大致如下:

server {
  listen 8080;
  server_name docker.registry.in.my.com;
  client_max_body_size 0;
  chunked_transfer_encoding on;

  access_log    /var/log/nginx/docker-registry-access.log;
  error_log     /var/log/nginx/docker-registry-error.log;

  location / {
    # 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://127.0.0.1:5000;
    proxy_set_header  Host              $http_host;
    proxy_set_header  X-Real-IP         $remote_addr;
    proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Proto https;
    proxy_set_header  X-Original-URI    $request_uri;
    proxy_set_header  Docker-Distribution-Api-Version   registry/2.0;
    proxy_read_timeout                  900;
  }
}

過程中我遇到的幾個大地雷有:

  • Ubuntu 14.04 內的 nginx 版本太舊,不支援 add_header 的 always 指令,導致不會送出該識別 header,所以 docker login 會判斷這個 docker-registry 為 Invalid registry endpoint,解決方法就是要從 nginx 官網裝新版(至少 1.7.5 以上,這顆地雷是從 [Running Secured Docker Registry 2.0 – Container Solutions] 這篇看到提示才解掉的)。
  • 由於 nginx <-> docker-registry 之間通訊是走 http://,所以在 push image 的時候,一開始從 remote 下 PUT 指令還是 https://,但是接著 docker-registry 會根據 X-Forwarded-Proto 的值送出 Location: http://xxx HTTP header 請 client 轉址,導致接下來的 PUT 操作失敗,解決方法就是要把 X-Forwarded-Proto 強制指定為 https

幾個經驗:

  • 善用 curl -v 給的資訊來判斷,不要瞎猜。
  • V2 目前還是很多坑,使得你不得不去看 source code,但是還好小的我還學過一點 Go

CC BY-SA 4.0 This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

Leave a Reply

Your email address will not be published. Required fields are marked *