基于OSS搭建私有 Docker Registry
基于OSS搭建私有 Docker Registry
Docker Registry 作为 Docker 的核心组件之一负责了镜像的存储以及分发。用户只需要使用 Docker 的客户端就可以直接和 Registry 进行交互,下载和上传镜像。最初版本的 Registry 由 Python 实现。由于设计初期在安全性,性能以及 API 的设计上有着诸多的缺陷,该版本在 0.9 之后停止了开发。新的项目由 Go 语言开发,所有的API,底层存储方式,系统架构都进行了全面的重新设计已解决上一代 Registry 中存在的问题。
准备工作
- 安装 Docker Engine
curl -sSL http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/internet | sh -
- 安装 Docker Compose
sudo curl -sSL http://mirrors.aliyun.com/docker-toolbox/linux/compose/1.7.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
sudo chmod a+x /usr/local/bin/docker-compose
- 配置加速器,下载 Registry 镜像
下载镜像之前,推荐先配置阿里云的加速器,可以节省大量下载镜像的时间。帮助链接
docker pull registry:2.4.1
部署私有 Docker Registry
- 为 Registry 相关的配置新建一个单独的目录
mkdir registry && cd registry
- 在当前目录下新建我们的账户密码(最简单的账户验证方式)
mkdir auth
htpasswd -Bbn admin 123456 > auth/htpasswd
- 在当前目录下新建我们的容器编排文件 docker-compose.yml
注意这个文件中的一些OSS相关的信息,例如AK、Bucket,需要用户根据自己的情况填写。
registry:
restart: always
image: registry:2.4.1
ports:
- 80:5000
volumes:
- ./auth:/auth
environment:
- REGISTRY_AUTH=htpasswd
- REGISTRY_AUTH_HTPASSWD_REALM=basic-realm
- REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd
- REGISTRY_STORAGE=oss
- REGISTRY_STORAGE_OSS_ACCESSKEYID=<accesskey_id>
- REGISTRY_STORAGE_OSS_ACCESSKEYSECRET=<accesskey_secret>
- REGISTRY_STORAGE_OSS_REGION=<region_id>
- REGISTRY_STORAGE_OSS_BUCKET=<bucket_name>
详细的OSS STORAGE的配置文档在这里:https://docs.docker.com/registry/storage-drivers/oss/
ECS部署通过内网访问OSS,请配置REGISTRY_STORAGE_OSS_INTERNAL环境变量。
如果默认域名不正确,请使用REGISTRY_STORAGE_OSS_ENDPOINT环境变量。
- 启动 Registry
# 如果你不需要看日志的话,可以加 -d 参数后台启动
docker-compose up
如果启动成功会看到控制台打印出容器监听5000端口的信息
- 服务端测试
保持着这个终端,我们可以随时看到Registry运行时的日志信息,我们另开一个终端测试。
我们测试的步骤是,创建一个新的镜像,然后登陆Registry,最后上传。
docker tag registry:2.4.1 127.0.0.1/test/registry
docker login 127.0.0.1
docker push 127.0.0.1/test/registry
我们可以登陆 OSS 的控制台,看看Bucket里面是否有新增的内容。
- 客户端测试
首先在客户端,我们就需要通过服务器IP来访问我们的Registry了。
docker tag registry:2.4.1 xxx.xxx.xxx.xxx/test/registry
docker login xxx.xxx.xxx.xxx
docker pull xxx.xxx.xxx.xxx/test/registry
但是我们在登陆的时候肯定会遇到以下问题
Error response from daemon: invalid registry endpoint https://xxx.xxx.xxx.xxx/v0/: unable to ping registry endpoint https://xxx.xxx.xxx.xxx/v0/
v2 ping attempt failed with error: Get https://xxx.xxx.xxx.xxx/v2/: dial tcp xxx.xxx.xxx.xxx:443: connection refused
v1 ping attempt failed with error: Get https://xxx.xxx.xxx.xxx/v1/_ping: dial tcp xxx.xxx.xxx.xxx:443: connection refused. If this private registry supports only HTTP or HTTPS with an unknown CA certificate, please add `--insecure-registry xxx.xxx.xxx.xxx` to the daemon's arguments. In the case of HTTPS, if you have access to the registry's CA certificate, no need for the flag; simply place the CA certificate at /etc/docker/certs.d/xxx.xxx.xxx.xxx/ca.crt
根据提示,我们需要把 --insecure-registry xxx.xxx.xxx.xxx
加到Docker Deamon的启动参数中。重启Deamon之后,我们再尝试一下登陆和镜像的推送就应该没有问题了。
- 包含证书的新配置文件
如果不希望出现这个报错的话,用户需要为自己的私有Registry购买一个独立的域名,并且购买域名的https证书。然后就可以通过在服务端配置证书,配置举例如下。
registry:
restart: always
image: registry:2.4.1
ports:
- 443:5000
volumes:
- ./ssl:/ssl
- ./auth:/auth
environment:
- REGISTRY_AUTH=htpasswd
- REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm
- REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd
- REGISTRY_HTTP_ADDR=0.0.0.0:5000
- REGISTRY_HTTP_SECRET=dXWOGobJypiDnN6W
- REGISTRY_HTTP_TLS_CERTIFICATE=/ssl/private.registry.com.crt
- REGISTRY_HTTP_TLS_KEY=/ssl/private.registry.com.key
- REGISTRY_STORAGE=oss
- REGISTRY_STORAGE_OSS_ACCESSKEYID=<accesskey_id>
- REGISTRY_STORAGE_OSS_ACCESSKEYSECRET=<accesskey_secret>
- REGISTRY_STORAGE_OSS_REGION=<region_id>
- REGISTRY_STORAGE_OSS_BUCKET=<bucket_name>
既然已经使用https的证书了,我们对外暴露的端口换成 443 端口。
将本地的证书目录也一并挂载到容器里面去。
添加了四个关于证书访问的配置,REGISTRY_HTTP_SECRET 是随机的加密串。REGISTRY_HTTP_TLS_KEY、REGISTRY_HTTP_TLS_CERTIFICATE 是证书和秘钥。
- 最后在展示一下示例中的文件结构:
|-- auth 账户信息目录(挂载到容器的 /auth 目录)
| `-- htpasswd 账户信息文件
|-- docker-compose.yml 应用编排模板
`-- ssl 证书目录 (挂载到容器的 /ssl 目录)
|-- private.registry.com.cer Https证书
`-- private.registry.com.key 证书秘钥
阿里云容器Hub服务的优势
阿里云的容器Hub服务则在镜像的存储与分发的基础之上,提供了大量额外的服务。不管是在服务的稳定性还是可用性上,都能有一个更为可靠的保证。并且可以和更多的服务串联起来,为应用生命周期全流程的自动化提供了基础。
容器Hub服务 控制台链接: https://cr.console.aliyun.com
元信息管理
- Docker Registry 的功能是镜像的存储和分发,并没有镜像的管理功能。所以当我们搭建了一个私有 Registry 之后,镜像的元信息管理是缺失的。这就意味着我们并不知道我们的 Registry 中有什么镜像,我们必须开发一个应用来管理镜像的元信息。
- 容器Hub服务拥有镜像元信息的管理功能。通过控制台可以轻松的查询到你拥有的仓库,仓库中存在的各个版本的镜像以及镜像的推送时间等信息。
账户信息管理
- 在上面搭建Registry的例子中,我们的账户信息是存储在一个文件中的,这仅仅是账户管理的最简单的方式。使用这种方式管理用户账户的话,需要手动维护账户信息的文件。如果需要更为灵活的账户管理服务,用户需要再自己部署一个Auth服务,并且配置到Registry中,通过实现鉴权的约定接口为用户账户信息进行管理。
- 容器Hub服务部署了自己的Auth服务,对所有用户的账户信息进行管理,同时对每个账户的权限进行管理。并且允许用户对自己的镜像或仓库做出授权操作,授权其他用户下载或是更新自己的镜像或仓库。完善的账户管理功能可以规避掉因为账户管理不善导致的信息安全问题。
构建服务
- 镜像的构建也是一件费时费力的事情,而且在国内构建更是。构建镜像时,我们经常会使用到一些国外软件源,缓慢的下载速度极大的影响了开发的效率。甚至构建难以成功。
- 容器Hub服务针对这个问题,提供了镜像构建服务。用户可以针对镜像的特性,选择国外构建环境进行构建,构建完成之后,构建服务会将镜像推送回仓库。用户只需要在创建仓库时,绑定指定的代码源地址就可以了。作为开发自动化的一部分,用户还可以开启自动构建功能,容器Hub服务会接收源代码仓库的回调信息,在开发者推送新的代码之后,自动进行构建完成镜像上传。
Webhook
- 作为开发自动化的另一环,在用户镜像更新之后,可能需要进行测试、部署等动作。容器Hub服务提供了Webhook钩子,用于镜像更新之后的流程触发。例如现在的一个典型场景就是,镜像更新之后,容器Hub服务主动触发容器服务的OpenAPI接口,更新部署的镜像并重启。
成本相关(域名、证书、运维)
- 对系统整体的监控报警保证了容器Hub服务的可用性,免去了普通用户对 Registry 运维上的成本。
注意:
支持ip登录私仓库
1.
用openssl生成自签名的证书:
我们直接在root用户下操作,创建一个目录: /root/certs
然后执行:
openssl req -newkey rsa:2048 -nodes -sha256 -keyout /root/certs/domain.key -x509 -days 365 -out /root/certs/domain.crt
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:bj
Locality Name (eg, city) [Default City]:bj
Organization Name (eg, company) [DefaultCompany Ltd]:mycom
Organizational Unit Name (eg, section)[]:it
Common Name (eg, your name or your server'shostname) []:129.144.150.111
Email Address []:[email protected]
执行成功后会生成:domain.key 和domain.crt 两个文件
COPY证书
使用Docker Registry的Docker机需要将domain.crt拷贝到 /etc/docker/certs.d/[docker_registry_domain:端口或者IP:端口]/ca.crt,
cp domain.crt/etc/docker/certs.d/129.144.150.111:5000/ca.crt
将domain.crt内容放入系统的CA bundle文件当中,使操作系统信任我们的自签名证书。
CentOS 6 / 7或者REDHAT中bundle文件的位置在/etc/pki/tls/certs/ca-bundle.crt:
cat domain.crt >>/etc/pki/tls/certs/ca-bundle.crt
Ubuntu/Debian Bundle文件地址/etc/ssl/certs/ca-certificates.crt
cat domain.crt >> /etc/ssl/certs/ca-certificates.crt
注意,如果之前已经有cat过同样的IP, 需要到ca-bundle.crt中把它删除,再做cat操作。否则后面PUSH时会报:
Get https://129.144.150.111:5000/v1/_ping:x509: certificate signed by unknown authority
重启DOCKER Daemon, Registry
systemctl restart docker
启动REGITRY
docker-compose up
验证测试
确认HTTPS OK: curl -i -k -v https://129.144.150.111:5000
或者直接浏览器访问 https://129.144.150.111:5000/v2 显示{} 表示正常
[[email protected] certs]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos latest a8493f5f50ff 12 days ago 192MB
129.144.150.111:5000/c latest a8493f5f50ff 12 days ago 192MB
registry 2 136c8b16df20 12 days ago 33.2MB
registry latest 136c8b16df20 12 days ago 33.2MB
hello-world latest 48b5124b2768 3 months ago 1.84kB
[[[email protected] certs]# docker push129.144.150.111:5000/c
The push refers to a repository[129.144.150.111:5000/c]
36018b5e9787: Pushing 28.9MB/192.5MB
成功
在别的机器*问
如果要在另一台机器*问,需要把CERT文件 COPY过去,同样放在/etc/docker/certs.d下面,建一个目录:/129.144.150.111:5000,然后
[[email protected] ~]$ cp domain.crt/etc/docker/certs.d/129.144.150.111:5000/ca.crt
否则报:Error: API error (500): unable to ping registry endpointhttps://129.144.150.111:5000/v0/ v2 ping attempt failed with error: Gethttps://129.144.150.111:5000/v2/: x509: certificate signed by unknown authorityv1 ping attempt failed with error: Get https://129.144.150.111:5000/v1/_ping:x509: certificate signed by unknown authority
测试:
[[email protected] opc]# sudodocker pull 129.144.150.111:5000/c
Using default tag: latest
latest: Pulling from c
Digest:sha256:1164a179f7328c80edab409118c4cf0986ffe143b3693c7769f6d54e098705e3
Status: Image is up to date for129.144.150.111:5000/c:latest
自签证书的处理
参考文献:
上一篇: Docker 创建私有仓库