楔子
我们一般测试开发的时候,都习惯于直接从公共镜像仓库hub.docker.com
拉取所需镜像,但是实际生产环境中可能涉及自建镜像和网络等各方面的原因,这个时候或许预先搭建自己的镜像仓库可能会更方便些,如下就来讲讲基于证书访问的docker registry
的搭建流程。
创建自签名证书
首先,不管是Registry客户端还是服务器端都默认已经安装docker、openssl等工具。另外这儿Registry Server和客户端是一台主机且IP是10.0.2.15
,域名vienfu.dockerhub.com
,因此要做域名的解析配置:
echo "10.0.2.15 vienfu.dockerhub.com" >> /etc/hosts
然后开始创建自签名证书:
mkdir -p /root/certs.d
cd /root/certs.d
openssl req -newkey rsa:2048 -nodes -sha256 -keyout ./domain.key -x509 -days 365 -out ./domain.crt # 根据提示依次填入所需信心,注意Common Name处要填入之前被解析的域名vienfu.dockerhub.com
# 客户端证书拷贝
mkdir -p /etc/docker/certd.d/vienfu.dockerhub.com:5000
cp /root/certs.d/domain.crt /etc/docker/certd.d/vienfu.dockerhub.com:5000/ca.crt
# 如果后续欲通过curl证书访问registry接口,还需要做如下操作:
cat /root/certs.d/domain.crt >> /etc/ssl/certs/ca-certificates.crt
以上所有操作完成后,重启docker
:systemctl restart docker
创建Registry容器
首先,可以预先拉取registry
镜像:
docker pull registry:2
如果考虑到持久化和镜像的删除问题,可以预先做如下操作:
mkdir -p /root/docker_image_mgr/registry
cat << EOF >> /root/docker_image_mgr/config.yml
version: 0.1
log:
fields:
service: registry
storage:
delete:
enabled: true # 其中delete.enabled是为镜像删除设置的字段
cache:
blobdescriptor: inmemory
filesystem:
rootdirectory: /var/lib/registry
http:
addr: :5000
headers:
X-Content-Type-Options: [nosniff]
health:
storagedriver:
enabled: true
interval: 10s
threshold: 3
EOF
启动registry
容器:
docker run -d -p 5000:5000 --name my-registry -v /root/docker_image_mgr/registry:/var/lib/registry -v /root/docker_image_mgr/config.yml:/etc/docker/config.yml -v /root/certs.d:/root -e REGISTRY_HTTP_TLS_CERTIFICATE=/root/domain.crt -e REGISTRY_HTTP_TLS_KEY=/root/domain.key registry:2
# 启动之后,docker ps看一下启动状态
root@kolla:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ed96182fa77d registry:2 "/entrypoint.sh /etc/" 15 hours ago Up 15 hours 0.0.0.0:5000->5000/tcp my-registry
如此Registry Server
启动完成,下面不妨测试一下可否向该Registry Server
上传镜像。
docker tag hello-world vienfu.dockerhub.com:5000/hello-world:test
docker push vienfu.dockerhub.com:5000/hello-world:test
简单通过curl
命令来查看镜像是否上传:
root@kolla:~#curl -X GET https://vienfu.dockerhub.com:5000/v2/_catalog
{"repositories":["hello-world"]}
如此我们看到镜像也的确上传成功了。
仓库加鉴权
出于安全考虑,一般在认证之后还需要做一个鉴权来控制用户的访问权限,这儿仅介绍最基本的鉴权方式:用户名和密码访问模式。
首先创建一个用户及访问的密码,这儿假设用户名和密码分别是vienfu、Fch19880810
:
mkdir -p /root/auth
docker run --entrypoint htpasswd registry:2 -Bbn vienfu Fch19880810 > /root/auth/htpasswd
然后把之前起的容器停掉并且删除:
docker stop my-registry
docker rm my-registry
最后启动一个带鉴权的registry
容器:
docker run -d -p 5000:5000 --name my-registry \
-v /root/auth:/auth \
-v /root/docker_image_mgr/registry:/var/lib/registry \
-v /root/docker_image_mgr/config.yml:/etc/docker/registry/config.yml \
-v /root/certs.d:/root \
-e "REGISTRY_AUTH=htpasswd" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/root/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/root/domain.key \
registry:2
那也不妨测试一下,实际上我们不难发现,这个时候如果我们直接docker push
来上传镜像会失败,这是因为设置了鉴权访问的参数需要先做如下操作:
docker login vienfu.dockerhub.com:5000 # 根据提示输入之前设置的用户名和密码
如此我们再通过docker push
上传镜像就ok
啦,最后也通过curl
命令来查看一下吧:
root@kolla:~# curl -u vienfu:Fch19880810 -X GET https://vienfu.dockerhub.com:5000/v2/_catalog
{"repositories":["hello-world"]}
好啦,自此私有镜像仓库的搭建工作算是完成了。
结语
以上完整讲述了私有镜像仓库的搭建流程,但实际生产环境中可能会涉及高可用、异地数据同步及一致性等问题,这些问题都需要我们去一一解决(这儿暂不做这方面的展开);另外,企业级应用还可以考虑使用Harbor
,它会提供一整套的解决方案包括用户管理、操作界面、镜像签名、漏扫、高可用等一系列功能,刚兴趣的同学可参照我的另两篇博客:基于NFS后端存储搭建Harbor和基于CEPH后端存储搭建Harbor。