用docker搭建本地docker registry

Docker镜像构建以后,如果想存起来或者分享,一般都存放到dockerhub,或者临时存放到ttl.sh。但dockerhub是有容量限制的,因而自己搭建docker registry也是个不错的选择,而且使用起来也很简单(这归功于docker简单的tag机制,在tag中包含registry前缀即可方便push到不同的地方)。

Docker官方提供了registry的镜像,部署起来比较方便–只有ssl证书方面比较麻烦。

为了部署私有registry,大致上有这么几个要点:

  1. 准备好ssl签名(自签名)。
  2. 在宿主机选好配置文件、registry存储目录。部署稳定的registry:2镜像。
  3. 在客户端信任ssl根证书。

准备自签名SSL证书

生成根证书

先产生私钥文件:

1
2
mkdir root_ca
openssl ecparam -out root_ca/ROOT_CA_PRIVATEKEY.key -name secp384r1 -genkey

还可以选更加简单的 prime256v1 加密算法替换 secp384r1。

创建CSR:

1
openssl req -new -sha256 -key root_ca/ROOT_CA_PRIVATEKEY.key -out root_ca/ROOT_CA_CSR.csr -subj "/C=CN/ST=GD/L=GZ/OU=ALL/O=test/CN=test"

其中信息缩写:

  • CN - CommonName
  • L - LocalityName
  • ST - StateOrProvinceName
  • O - OrganizationName
  • OU - OrganizationalUnitName
  • C - CountryName

创建配置文件ROOT_CA.cnf

1
2
3
4
5
cat > root_ca/ROOT_CA.cnf
basicConstraints=critical,CA:TRUE
nsComment = "comment"
keyUsage=critical, keyCertSign
subjectKeyIdentifier=hash

创建根证书:

1
openssl x509 -req -sha256 -days 36500 -extfile root_ca/ROOT_CA.cnf -in root_ca/ROOT_CA_CSR.csr -signkey root_ca/ROOT_CA_PRIVATEKEY.key -out root_ca/ROOT_CA_CERT.crt

到此,所有文件为:

1
2
3
% ls root_ca 
ROOT_CA.cnf ROOT_CA_CSR.csr
ROOT_CA_CERT.crt ROOT_CA_PRIVATEKEY.key

用根证书颁发域名证书(假设域名为mysvr)

创建key和CSR

1
2
3
mkdir mysvr_certs
openssl ecparam -out mysvr_certs/mysvr.key -name prime256v1 -genkey
openssl req -new -subj "/C=CN/ST=GD/O=test/OU=LAN/CN=mysvr" -key mysvr_certs/mysvr.key -out mysvr_certs/mysvr.csr

创建ssl.cnf配置文件,用于颁发证书

1
2
3
4
5
6
7
8
9
10
cat > mysvr_certs/ssl.cnf
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1= mysvr.local
DNS.2= mysvr.lan
IP.1 = 192.168.0.121

通过CA为mysvr的CSR颁发证书mysvr.crt。

首次生成crt:

1
openssl x509 -req -CA root_ca/ROOT_CA_CERT.crt -CAkey root_ca/ROOT_CA_PRIVATEKEY.key -CAcreateserial -days 398 -sha256 -extfile mysvr_certs/ssl.cnf -in mysvr_certs/mysvr.csr -out mysvr_certs/mysvr.crt

首次生成crt会通过-CAcreateserial参数产生srl文件在root_ca/ROOT_CA_CERT.srl,以后再度颁发证书则用首次的srl即可:

1
2
cp root_ca/ROOT_CA_CERT.srl mysvr_certs/mysvr.srl
openssl x509 -req -CA root_ca/ROOT_CA_CERT.crt -CAkey root_ca/ROOT_CA_PRIVATEKEY.key -CAserial mysvr_certs/mysvr.srl -days 398 -sha256 -extfile mysvr_certs/ssl.cnf -in mysvr_certs/mysvr.csr -out mysvr_certs/mysvr.crt

验证证书是否可信:

1
openssl verify -CAfile root_ca/ROOT_CA_CERT.crt mysvr_certs/mysvr.crt

mysvr_certs/mysvr.crt: OK

如果以后要更新IP,则需要修改cnf,再重新颁发即可。

部署docker registry

我这里部署到群晖的nas上,其docker服务界面支持设置环境变量(命令行 -e)、端口(-p)、文件路径(-v),整体设置如下:

运行registry:2镜像,设置环境变量:

1
2
REGISTRY_HTTP_TLS_CERTIFICATE=/certs/mysrv.crt
REGISTRY_HTTP_TLS_KEY=/certs/mysrv.crt

上述路径为映射的路径。

设置路径映射:

1
2
3
docker/docker-registry/registry:/var/lib/registry
docker/docker-registry/config.yml:/etc/docker/registry/config.yml
docker/mysrv/certs:/certs

上传证书文件到宿主机的docker/mysrv/certs目录下。

设置端口:

1
4000:4000

在客户端信任证书(安装根证书)

macos下让浏览器信任证书

安装根证书,双击,添加到login items,然后到Keychain Access里面找到test证书,确认信息,然后选择always trust。

此时浏览器已经能信任该证书。对于docker,只要重启engine即可。

Linux下让docker信任证书

本质上是复制根证书到docker客户端的registry配置目录内,然后重启即可。

docker registry证书在 /etc/docker/certs.d/${domain}:${port}/ca.crt 目录。例如我们这里为:

1
2
cp root_ca/ROOT_CA_CERT.crt /etc/docker/certs.d/mysrv.local\:4000/ca.crt
sudo systemctl restart docker

在群晖的docker服务中添加我们自己的docker registry

主要两步:

1. 添加根证书到群晖系统

群晖的 /etc/ssl/certs/ca-certificates.crt 文件内存放了所有证书,这个文件是由 /usr/syno/bin/update-ca-certificates.sh 脚本根据 /var/db/ca-certificates 目录来维护的。

因而,要添加证书,则可以这样做:

1
2
3
sudo cp my_path_to_mysrv_root.crt /var/db/ca-certificates/mysrv_root.crt
sudo chmod 644 /var/db/ca-certificates/mysrv_root.crt
sudo update-ca-certificates.sh

这个证书还会被自动链接到这个位置:

1
2
3
4
$ ls -lh /etc/ssl/certs/`sudo openssl x509 -hash -noout -in /var/db/ca-certificates/mysrv_root.crt`*
lrwxrwxrwx 1 root root 13 Apr 8 22:41 /etc/ssl/certs/8528aafc.0 -> mysrv_root.pem
$ sudo ls -l /etc/ssl/certs/mysrv_root.pem
lrwxrwxrwx 1 root root 37 Apr 8 22:41 /etc/ssl/certs/mysrv_root.pem -> /var/db/ca-certificates/mysrv_root.crt

2. 添加根证书到群晖docker服务的配置目录

1
2
sudo mkdir -p /var/packages/Docker/etc/certs.d/mysrv.local:4000/
sudo my_path_to_mysrv_root.crt /var/packages/Docker/etc/certs.d/mysrv.local:4000/ca.crt

然后重启docker服务:

1
sudo systemctl restart pkgctl-Docker # 这个命令会比较久。

注意:使用.local域名的话,要注意主机上是否能解析(可以用ip)。

使用

支持,可以对镜像打tag并且push:

1
2
docker tag my/image mysrv.local:4000/my/image
docker push mysrv.local:4000/my/image

可通过url查询镜像:

1
https://mysrv.local:4000/v2/_catalog