写在前面:
Docker私有registry指的是在私有服务器上搭建的、用于管理Docker repositories的实体。可以理解成私有的Docker资源管理仓库。搭建Docker私有registry,本质上是从Docker官方库拉取registry
镜像,并在本地Docker中运行。Docker官方文档介绍了搭建的步骤。但是在实际部署中,会遇到一些文档中没有详细描述的情况和问题。这篇博文记录了部署私有registry并配置https的完整步骤,并且探讨了存储空间不足的一些解决方案。
部署环境
- 操作系统:Centos7
- 已经安装好Docker CE版
- 可以联网
基本步骤
在命令行通过以下命令就可以启动一个本地的registry:
$ docker run -d -p 5000:5000 --restart=always --name registry registry:2
该registry运行在localhost的5000端口,使用
http
协议.--restart=always
表示该实例遇到问题会自动重启,--name registry
表示名字是registry
。可以自己起名。向本地私有registry推送镜像
从Docker Hub上拉取一个镜像,例如
ubuntu:16.04
:$ docker pull ubuntu:16.04
将此镜像tag为
localhost:5000/my-ubuntu
:$ docker tag ubuntu:16.04 localhost:5000/my-ubuntu
注意,此处必须指明
<host:port>
,否则后续会默认push到官方Docker Hub上。将tag的镜像推送到本地的私有registry:
$ docker push localhost:5000/my-ubuntu
删除本地的镜像,尝试从私有registry中拉取:
删除:$ docker image remove ubuntu:16.04
$ docker image remove localhost:5000/my-ubuntu
拉取:
$ docker pull localhost:5000/my-ubuntu
- 在步骤2中,可能会遇到拉取镜像慢的问题(Docker Hub服务器在海外)。建议使用国内镜像加速。参考Docker 中国官方镜像加速
终止registry运行
$ docker stop registry
也可以删除容器:
$ docker stop registry && docker rm -v registry
在部署过程中,如果遇到registry不断重启的情况,可以查看docker运行日志来诊断问题:
docker logs --tail 50 --follow --timestamps <your_container_name/id>
对registry的运行时配置
registry
本质上也是一个容器,可以使用docker run
命令运行。运行时是使用root
用户还是普通用户,取决于安装时使用的用户。基本的运行方法,就如上文所述。
自动重启
$ docker run -d -p 5000:5000 --restart=always --name registry registry:2
重点在于
--restart=always
自定义端口号
$ docker run -d -p 5050:5000 --restart=always --name registry-test registry:2
这条指令会在localhost的5050端口启动一个名为
registry-test
的registry容器。在容器内部,则监听5000
端口。
可以通过REGISTRY_HTTP_ADDR
命令改变容器内部监听的端口:$ docker run -d -e REGISTRY_HTTP_ADDR=0.0.0.0:5001 -p 5050:5001 --name registry-test registry:2
这样在容器内部,会监听
5001
端口。自定义本地存储路径
$ docker run -d -p 5000:5000 --restart=always --name registry -v /mnt/registry:/var/lib/registry registry:2`
该指令将registry内部的
/var/lib/registry
映射到本机的/mnt/registry
路径,推送到该registry的镜像就会都保存在本地的/mnt/registry
路径下。
搭建可外部访问的registry (https)
上文所描述的步骤,是用于在本地搭建一个私有registry. 如果需要搭建外部可访问的registry,需要有https的证书,然后使用域名访问你的私有registry.
假设域名为reg.example.org
。
先创建一个certs
路径:
$ mkdir -p certs
如果你已经有自己的证书,将你的.crt
和.key
文件直接拷贝到certs
路径。
如果使用的是intermediate证书,需要做如下处理:
- 若你有
.crt
和.pem
文件:
cat domain.crt intermediate-certificates.pem > certs/domain.crt
- 若你有
.crt
和IntermediateCA.crt
文件(我是这种情况):
cat ssl_certificate.crt IntermediateCA.crt > certs/domain.crt
注意:必须先放自己的ssl证书,再拼接intermediaCA,否则会由于证书错误导致registry不断重启、不能提供服务。
使用如下指令启动registry:
docker run -d --restart=always --name testreg \
-v `pwd`/certs:/certs \
-e REGISTRY_HTTP_ADDR=0.0.0.0:80 \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
-p 80:80 \
registry:2
我在80
端口启动了registry. 因此所有要push到这个registry的镜像,都需要在打tag的时候指明域名和ip:reg.example.org:80/my-ubuntu
。如果tag中没有指明端口号,则docker会默认使用443端口(https的端口号)。如果你的私有registry刚好指定运行在443端口上,则ok没问题;如果不是在443端口,就会报错访问被拒绝。
通过用户管理控制访问权限
可以通过docker指令创建用户,以限制访问权限。
创建用户:
$ mkdir auth
$ docker run \
--entrypoint htpasswd \
registry:2 -Bbn testuser testpassword > auth/htpasswd
用户名是testuser
,密码是testpassword
。
终止registry,以新的参数重新启动:
$ docker stop testreg
$ docker run -d \
--restart=always \
--name testreg \
-p 80:5000 \
-v `pwd`/auth:/auth \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
-v `pwd`/certs:/certs \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
registry:2
这时,再尝试push或pull,就会失败,因为需要登录:
$ docker login reg.example.org:80
通过compose文件启动
可以为registry创建docker-compose.yml文件,便于启动。大概长这样:
registry:
restart: always
image: registry:2
ports:
- 80:5000
environment:
REGISTRY_HTTP_TLS_CERTIFICATE: /certs/domain.crt
REGISTRY_HTTP_TLS_KEY: /certs/domain.key
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
volumes:
- /path/data:/var/lib/registry
- /path/certs:/certs
- /path/auth:/auth
关于本地存储空间不够的问题
经常性地提交新的docker镜像,会占用registry服务器大量的空间。为了解决这个问题,需要在docker-compose.yml
文件中,增加以下环境变量的配置:
REGISTRY_STORAGE_DELETE_ENABLED: "yes"
然后,重启registry。
可以参考以下两篇博文:
docker registry 镜像删除
谁用光了磁盘?Docker System命令详解
核心命令是:
查询镜像信息:
curl --header "Accept: application/vnd.docker.distribution.manifest.v2+json" -I -X GET <protocol>://<registry_host>/v2/<repo_name>/manifests/<tag>
删除镜像:
curl -I -X DELETE <protocol>://<registry_host>/v2/<repo_name>/manifests/<digest_hash>
删除文件系统内的镜像:
docker exec -it <registry_container_id> bin/registry garbage-collect /etc/docker/registry/config.yml
注意:
1. 要先修改config.yml
。我是在/
目录下find的。好像启动的时候可以指定位置。
2. 在centos中,config.yml
的位置,就是/etc/docker/registry/config.yml