基于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.cer
        - 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 运维上的成本。

相关链接

容器Hub服务 控制台
Docker Registry 配置参考文档
Docker Engine 镜像源站
Docker Toolbox 镜像源站
Docker 镜像加速器

上一篇:Linux磁盘阵列技术详解(三)--raid 5和raid 10的创建 推荐


下一篇:Structured Streaming生产化实践及调优