搭建私有 Docker Registry

为了团队的其他同学可以方便的更新开发环境到本地,我们决定搭建私有的 Docker Registry。
不使用公共服务的原因:

  1. Docker Hub 在国外,同步超级慢。
  2. DaoCloud 的私有 image 需要收费,对于我们小团队来说不太友好。

搭建步骤

  1. 环境准备。
  2. 配置 LetsEncrypt 证书。
  3. 安装 Docker Registry。
  4. 配置 Nginx。
  5. 后续工作。

环境准备

  1. Linux 服务器一台。
  2. 域名。
  3. 已经安装上 Docker 和 Nginx。

注意:开发环境和服务器的 Docker 都先升级到最新的版本,否则有可能出现未知的失败。

目录结构
dfa3f652e14eda27.png

配置 LetsEncrypt 证书

由于私有 Docker Registry 的安全机制,需要使用 Https,原因

配置 LetsEncrypt 证书 使用 certbot

wget https://dl.eff.org/certbot-auto
chmod a+x certbot-auto
$ ./certbot-auto

./path/to/certbot-auto certonly --standalone -d registry.yourdomain.com

安装的时候必须先关闭 Nginx 服务否则无法生成证书
LetsEncrypt 只支持二级域名,而且有域名个数限制,提前想好私有 Docker Registry 的二级域名

安装 Docker Registry

使用 daocloud 上的 docker registry 公共镜像

docker pull daocloud.io/library/registry:2

将 LetsEncrypt 证书复制到 /certs

cp /etc/letsencrypt/live/yourdomain/fullchain.pem certs/
cp /etc/letsencrypt/live/youdomain/privkey.pem certs/

生成认证文件

docker run --entrypoint htpasswd daocloud.io/library/registry:2.4.1 -Bbn username password > auth/htpasswd

配置 docker-compose.yml

# docker-compose.yml
registry:
  restart: always
  image: daocloud.io/library/registry:2
  ports:
    - 5000:5000
  environment:
    # Example use Lensencrypt cert
    REGISTRY_HTTP_TLS_CERTIFICATE: /certs/fullchain.pem
    REGISTRY_HTTP_TLS_KEY: /certs/privkey.pem
    REGISTRY_AUTH: htpasswd
    REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
    REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
  volumes:
    # Replace those three path
    - /path/registry:/var/lib/registry
    - /path/certs:/certs
    - /path/auth:/auth

运行

docker-compose up

测试浏览器访问

https://yourdomain.xxx:5000/v2

测试push

docker login yourdomain.xxx:5000
# 输入之前配置好的用户名密码

docker pull redis
docker tag redis yourdomain.xxx:5000/redis
docker push yourdomain.xxx:5000/redis

成功的效果
5860b16d5aa8d17a.jpg

配置 Nginx 做反向代理

配置文件 docker_nginx.conf

# this is necessary for us to be able to disable request buffering in all cases
proxy_http_version 1.1;

server {
    listen 443 ssl;
    server_name registry.youdomain.com;

    # SSL
    # Replace with your cert
    ssl_certificate /path/certs/fullchain.pem;
    ssl_certificate_key /path/certs/privkey.pem;

    # 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 /v1/ {
      return 404;
    }

    location /v2/ {
      proxy_pass https://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;

      # When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings.
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_buffering off;

    }
}

server {
    listen 80;
    # Replace with your domain
    server_name yourdomain;
    rewrite ^/(.*) https://$server_name/$1 permanent;
}

重新加载 Nginx 配置

# 软链接
ln -s /path/docker_nginx.conf /etc/nginx/site-enabled

# 测试
nginx -t

# 重新加载
nginx -s reload

浏览器测试

https://yourdomain.xxx/v2

# 需要输入之前配置好的用户名和密码

push 测试

docker login yourdomain.xxx
# 输入之前配置好的用户名密码
docker pull redis
docker tag redis yourdomain.xxx/redis
docker push yourdomain.xxx/redis

后续工作

由于 LetsEncrypt 证书 3 个月会自动过期,需要使用脚本做自动更新,配合 crontab 两个月更新一次

renew_cert.sh

#!/bin/bash

# renew cert
/letsencrypt/certbot-auto renew --pre-hook "service nginx stop" --post-hook "service nginx start"

# backup cert
cp /yourpath/docker-registry/certs/fullchain.pem /yourpath/docker-registry/certs/fullchain.pem.bak
cp /yourpath/docker-registry/certs/privkey.pem /yourpath/docker-registry/certs/privkey.pem.bak

# change cert
cp /etc/letsencrypt/live/yourdomain/fullchain.pem /yourpath/docker-registry/certs/fullchain.pem
cp /etc/letsencrypt/live/yourdomain/privkey.pem /yourpath/docker-registry/certs/privkey.pem

运行

sh renew_cert.sh

感谢

https://www.daocloud.io 提供国内的公共镜像服务