「Docker」- 部署 Registry 服务

  CREATED BY JENKINSBOT

问题描述

该笔记将记录:在 Linux 中,如何搭建 Docker 镜像仓库(Docker Registry);

解决方案

参考 Configuring a registry 手册,以获取更加详细的说明;

参考 Considerations for air-gapped registries. 手册,以获取隔离数据中心的部署方法

先在机器上安装 Docker,然后运行 registry 镜像;

搭建 Registry 服务

Docker 公开 Register 代码,我们能够自行运行 Register,搭建私有服务,放在防火墙之后,但是没有用户界面,只能通过 API 访问;

运行服务

运行一个 Register 服务非常简单:docker run -p 5000:5000 registry:2,该命令启动一个 Registry 2.0 的容器,并将5000端口绑定到宿主机上。如果你的 Registry 低于 2.0 版本,则可以使用迁移工具「docker/migrator」来升级;

从 Docker 1.3.1 开始,需要在启动 Docker 守护进程的命令中添加--insecure-registry localhost:5000标志,并重启守护进程,才能使用本地 Registry 服务;

启动 Registry 容器:

docker run -d -p 5000:5000 --restart=always --name registry registry:2

至此容器已经启动;

上面的示例仅适用于测试环境的 Registry 配置。生产环境的 Registry 必须受 TLS 保护,理想情况下应使用「访问控制」机制。 「本文后续内容」及「configuration guide」以部署生产就绪的注册表;

推送镜像

测试新的 Registry 服务:
1)找到镜像 ID 值:docker images your/image
2)为镜像打标签:docker tag image_id docker.example.com:5000/jam/static_web
3)推送新的镜像:docker push docker.example.com:5000/jam/static_web
4)运行新的镜像:docker run -t -i docker.example.com:5000/jam/static_web

有关 Registry 的配置及管理参考官方的「Docker Registry | Docker Documentation」部署说明;

从 Docker Hub 拉取镜像到本地,然后重新打标,然后推送到本地的 Registry 中:

# 拉取
docker pull ubuntu:16.04

# 打标
docker tag ubuntu:16.04 localhost:5000/my-ubuntu

# 推到本地 Registry 中
docker push localhost:5000/my-ubuntu

# 删除镜像
docker image remove ubuntu:16.04
docker image remove localhost:5000/my-ubuntu

# 从 Registry 中拉去镜像
docker pull localhost:5000/my-ubuntu

停止服务

# 停止
docker container stop registry

# 停止并删除 Registry 服务
docker container stop registry && docker container rm -v registry               # 通过 -v 选项删除孤立的卷

修改基本配置

通过为docker run指定选项来控制某些行为,详细参考「registry configuration reference」手册;

自动启动容器:在「Docker 重启」或者「容器退出」时自动启动容器,则可以使用--restart=always选项;

修改端口号:使用-p 5001:5000选项修改暴露的端口号。使用-e REGISTRY_HTTP_ADDR=0.0.0.0:5001修改内部端口号;

自定义存储位置:默认使用 Docker 卷来存储 Registry 数据,如果要自定义路径,则可以使用-v选项指定挂载路径。也可以使用其他的后端存储,参考「storage configuration options」手册;

运行外部可访问的 Registry 服务

本地可访问的 Registry 功能有限。如果想外部可访问,则要先配置 TLS 证书;

使用正常证书

# 启动容器,并指定镜像
docker run -d \
  --restart=always \
  --name registry \
  -v "$(pwd)"/certs:/certs \
  -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
  -p 443:443 \
  registry:2

# 拉去,打标,推送
docker pull ubuntu:16.04
docker tag ubuntu:16.04 myregistrydomain.com/my-ubuntu
docker push myregistrydomain.com/my-ubuntu

证书颁发者可以为你提供中间证书。在这种情况下,必须将证书与中间证书连接在一起以形成证书包。进行一步额外的操作:

cat domain.crt intermediate-certificates.pem > certs/domain.crt

支持 Let’s Encrypt 证书

Registry 支持使用 Let’s Encrypt,来自动获取浏览器可信证书。有关 Let’s Encrypt 的更多信息,请参阅「Let’s Encrypt/How It Works」以及「registry configuration」相关部分;

使用不安全的 Registry 服务(仅测试)

不安全的 Registry 服务有两个方案:
1)使用 HTTP 协议;
2)使用自签名证书;

参考「run an insecure registry」部分的详细说明;

# 使用 HTTP 协议:使用 HTTP 协议的 Registry 服务就不再介绍,因为没法在公网部署。主要是因为不安全的 Register 服务无法使用 Basic Auth 认证,换作其他高级认证更麻烦,资源不允许;

# 使用自签名证书:这里介绍一下在 Linux 中使用自签名证书的 Registry 服务的部署,使用 Basic Auth 认证,并提供公网访问:

#!/bin/sh

# 我们使用 registry.d3rm.org 作为 CN 值

################################################################################
# 创建证书
################################################################################
mkdir -p certs

openssl req \
  -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key \
  -x509 -days 365 -out certs/domain.crt
# 注意 CN 名为域名,这里使用 registry.d3rm.org 作为 CN 值;

################################################################################
# 指示 Docker 信任 CA
################################################################################
mkdir -pv /etc/docker/certs.d/registry.d3rm.org:5000/
cp certs/domain.crt /etc/docker/certs.d/registry.d3rm.org:5000/ca.crt
systemctl restart docker.service

# !!!这里的操作分为两此,Client 和 Server 都要进行该操作。否则会产生「X509 errors」错误,这
# 个错误通常都是由于整数配置不正确导致的;

################################################################################
# 使用 TLS 启动 Registry 服务
################################################################################
mkdir auth
docker run --entrypoint htpasswd registry:2 -Bbn testuser testpassword > auth/htpasswd
docker run -d \
  -p 5000:5000 \
  --restart=always \
  --name registry \
  -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

################################################################################
# 测试
################################################################################
docker login registry.d3rm.org:5000
docker push registry.d3rm.org:5000/dockerfile-from-image

作为服务来运行 Registry

Run the registry as a service

负载均衡的一些考虑

Load balancing considerations

限制访问

除了内网访问之外,应该给 Registry 加上访问限制;

使用 Basic Auth 认证

在进行这一步骤之前需要先配置 TLS 先。然后才能进行如下操作:

# 生成基础认证
htpasswd -Bbn testuser testpassword > auth/htpasswd

# 停止容器
docker container stop registry

# 启动容器并指定基础认证
docker run -d \
  -p 5000:5000 \
  --restart=always \
  --name registry \
  -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

# 至此,拉去镜像会失败,需要提供用户名密码来登录
docker login myregistrydomain.com:5000


# 注意事项:
# X509 errors: X509 错误通常表示尝试使用自签名证书,并且未正确配置 Docker 守护程序;

#2 更多高级认证

可以在 Registry 的前端加入一些代理,实现更高级的认证,参考「recipes list」手册;

Registry 还支持委派身份验证,将用户重定向到特定的受信任口令服务器。这种方法设置起来比较复杂,只有在需要完全配置 ACL,并且需要对 Registry 集成到全局授权和身份验证系统的更多控制时才有意义。参考「background information」和「configuration information here」手册;

此方法要求你实现自己的身份验证系统或利用第三方实现;

使用 Compose 文件部署 Registry 服务

Deploy your registry using a Compose file

有网闸的 Registry 服务

参考「Considerations for air-gapped registries」手册

参考文献

Docker/Deploy a registry server
How to Setup Docker Private Registry on CentOS 7.x / RHEL 7.x
Docker/Configuring a registry