基于Docker的持续集成方案(安装和配置docker镜像仓库) - Part.5
在《基于Docker的持续集成方案(介绍) - Part.1》中,有一个安装和配置环节,即私有的docker镜像仓库,本文将对此进行介绍。
获取证书
docker镜像仓库默认使用https协议,因此需要使用证书。证书可以自己生成(需要额外配置),也可以在云服务器提供商(阿里云、腾讯云)处申请,但前提是你得有一个域名。这里介绍的是在腾讯云处申请的证书。
下载到证书之后,默认的名称很长,可以重命名为ca.crt和ca.key。
如果没有域名,也可以自己生成证书,生成证书可以在服务器上使用下面的命令来完成。剩下的流程都一样。但是在实际使用中,可能会提示证书有误。如果没有记错,需要修改客户端的 /etc/docker/daemon.json 文件,然后添加 { "insecure-registries":["your.domain.com:5000"] }
(注意替换域名和端口号)。
执行下面命令生成证书:
openssl req -newkey rsa:4096 -nodes -sha256 -keyout ca.key -x509 -days 365 -out ca.crt
服务端运行registry镜像
首先,下载docker registry镜像到本地,并重新tag一个短名称:
docker pull registry.docker-cn.com/library/registry:2.6; \ docker tag registry.docker-cn.com/library/registry:2.6 registry:2.6; \ docker rmi registry.docker-cn.com/library/registry:2.6;
将上一步获取到的ca.crt和ca.key上传到/docker/certs文件夹下(如果没有就创建一下)。
执行下面的docker命令运行容器:
docker run -d -p 8041:5000 --restart=always --name registry \ -v /docker/certs:/certs \ -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/ca.crt \ -e REGISTRY_HTTP_TLS_KEY=/certs/ca.key \ registry:2.6
https的默认端口是443,因为可能会有很多应用需要使用443端口,所以在前端的nginx服务器上统一配置,此处的镜像仓库则使用8041端口。注意,容器内部默认使用的端口是5000,这里使用 -p 标识做了映射。
客户端推送镜像
接下来我们尝试在客户端推送镜像到刚创建好的镜像仓库。我们先从官方pull一个体积比较小的镜像。
docker pull hello-world
然后对该镜像进行tag重命名:
docker tag hello-world docker.we-app.net:8041/hello-world:1.0
如果要推送一个本地docker镜像到远程仓库,只需要将该镜像tag为:推送地址+名称+Tag。
最后执行docker push命令进行推送
docker push docker.we-app.net:8041/hello-world:1.0
随后,我们在浏览器访问:https://docker.we-app.net:8041/v2/_catalog,可以看到{"repositories":["hello-world"]},说明已经推送成功。还可以通过https://docker.we-app.net:8041/v2/hello-world/tags/list,查看推送的明细:{"name":"hello-world","tags":["1.0"]}
换一台客户端,执行 docker pull docker.we-app.net:8041/hello-world:1.0
,可以成功获取到镜像。
配置访问权限
通过上面的方式,尽管可以推送镜像也可以获取镜像,但可以看到仓库是完全公开的,运行在内网自己用用还行,但在公网上则需要为镜像仓库添加访问权限。一般情况下,镜像仓库的权限配置有几种方式,这里我使用最简单的basic auth基本验证。
在服务端,进入文件夹/docker/auth(如果没有则创建)。
执行下面的docker命令:
docker run --rm --entrypoint htpasswd registry:2.6 -Bbn user1 pwd123 >> dockerusers docker run --rm --entrypoint htpasswd registry:2.6 -Bbn user2 pwd123 >> dockerusers
上面的命令会创建两个用户 user1,user2,密码均为pwd123,然后保存到dockeruser文件中。
删除当前的registry容器:
docker stop registry; docker rm registry;
使用下面的命令重新运行registry容器:
docker run -d \ -p 8041:5000 \ --restart=always \ --name registry \ -v /docker/auth:/auth \ -e "REGISTRY_AUTH=htpasswd" \ -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \ -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/dockerusers \ -v /docker/certs:/certs \ -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/ca.crt \ -e REGISTRY_HTTP_TLS_KEY=/certs/ca.key \ registry:2.6
可以看到,上面主要是添加了三条REGISTRY_AUTH相关的指令,用来配置用户信息。
在客户端再次push之前tag过的hello-world镜像:
[root@dev57 ~]# docker push docker.we-app.net:8041/hello-world:1.0 The push refers to repository [docker.we-app.net:8041/hello-world] 2b8cbd0846c5: Preparing no basic auth credentials
此时可以看到no basic auth credentials,说明缺少用户认证信息。
使用 docker login docker.we-app.net:8041
,并输入上面配置的用户名和密码。再次执行docker push,则可以成功推送。
再次通过浏览器访问 https://docker.we-app.net:8041/v2/_catalog 查看镜像列表,则会要求输入账号密码:
同样,如果换一台客户端 ,当执行docker pull获取hello-world镜像时,仍然会提示缺少权限。
[root@dev55 ~]# docker pull docker.we-app.net:8041/hello-world:1.0 Error response from daemon: Get https://docker.we-app.net:8041/v2/hello-world/manifests/1.0: no basic auth credentials
在这台客户端上再执行一遍 docker login docker.we-app.net:8041
,便可以进行获取了。
配置nginx服务器进行转发
像上面这样使用,有一点不方便,就是每次都需要输入端口号:8041。可以通过在前端的nginx服务器上进行配置,对443端口进行转发,这样就可以直接通过docker.we-app.net访问镜像仓库了。
在服务器端修改nginx的配置:
server { listen 443; server_name docker.we-app.net; ssl on; ssl_certificate /docker/certs/ca.crt; ssl_certificate_key /docker/certs/ca.key; location / { proxy_pass https://localhost:8041; } }
重新加载nginx配置:
nginx -s reload
现在,去掉端口号,使用浏览器访问:https://docker.we-app.net/v2/_catalog,再次看到登录框,一切正常。然后在客户端执行docker pull docker.we-app.net/hello-world:1.0,提示缺少basci auth,然后像上面演示的重新docker login docker.we-app.net一遍就一切正常了。
至此,加入简单用户访问权限的远程docker镜像仓库便安装并配置成功了。
感谢阅读,希望这篇文章能给你带来帮助!