原文地址node
在部署 registry 以前须要如今主机上安装 Docker。registry 实际上就是运行在 Docker 中的 registry 镜像的实例。linux
本主题提供关于部署和配置 registry 的基本信息。要查看配置选项列表,请参考 配置手册。web
若是你有 air-gapped 数据中心,参考 air-gapped registries 的注意事项。redis
使用下面命令来启动 registry 容器:sql
registry 如今可使用了。docker
警告:前几个示例显示的 registry 配置仅适用于测试环境。生产环境的 registry 必须受 TLS 保护,而且应该使用访问控制机制。继续阅读下一篇 registry 配置指南 以在生产环境中部署 registry。json
能够从 Docker Hub 中提取镜像并将其推送到你的 registry。如下示例从 Docker Hub 中取出 ubuntu:16.04
镜像,并将其从新标记为 my-ubuntu
,而后将其放入本地 registry。最后,删除本地的 ubuntu:16.04
和 my-ubuntu
镜像,并从本地 registry 中取出 my-ubuntu
镜像。ubuntu
ubuntu:16.04
镜像$ docker pull ubuntu:16.04
localhost:5000/my-ubuntu
。这会会已经存在的镜像建立附加标签。标签第一部分是主机名和端口号,执行 push 操做时 Docker 将其解析为 registry 的位置。$ docker tag ubuntu:16.04 localhost:5000/my-ubuntu
localhost:5000
的本地 registry:$ docker push localhost:5000/my-ubuntu
ubuntu:16.04
和 my-ubuntu
镜像删除后,能够测试从你的本地 registry 中获取镜像。这不会删除你的 registry 中的 localhost:5000/my-ubuntu
镜像。windows
$ docker image remove ubuntu:16.04
$ docker image remove localhost:5000/my-ubuntu
localhost:5000/my-ubuntu
镜像$ docker pull localhost:5000/my-ubuntu
相似中止其余容器,经过 docker container stop
命令能够中止本地 registry:后端
$ docker container stop registry
经过 docker container rm
命令能够删除容器:
$ docker container stop registry && docker container rm -v registry
要配置容器,能够将附加选项或修改选项传递给 docker run
命令。
下面提供了配置 registry 的基本指导原则。更多详细信息,请参阅 registry 配置参考。
若是你但愿将 registry 用做永久性基础架构的一部分,则应将其设置为在 Docker 从新启动或退出时自动从新启动。本示例使用 --restart always
标志为 registry 设置从新启动策略。
$ docker run -d \
-p 5000:5000 \ --restart=always \ --name registry \ registry:2
若是端口 5000 已经被占用,或者你想运行多个本地 registry 来分隔关注的区域,则能够自定义 registry 的端口。下面的示例在端口 5001 上运行 registry,并将其命名为 registry-test
。请记住,-p
值的第一部分是主机端口,第二部分是容器内的端口。在容器中,registry 默认在端口 5000 上监听。
$ docker run -d \
-p 5001:5000 \ --name registry-test \ registry:2
若是要在容器中更改 registry 监听的端口(If you want to change the port the registry listens on within the container),可使用环境变量 REGISTRY_HTTP_ADDR
来更改它。此命令使 registry 监听容器内的端口 5001:
$ docker run -d \
-e REGISTRY_HTTP_ADDR=0.0.0.0:5001 \ -p 5001:5001 \ --name registry-test \ registry:2
默认状况下,registry 数据在主机文件系统上做为 docker卷 持久保存。若是要将 registry 内容存储在主机文件系统上的特定位置,例如挂载到特定目录的 SSD 或 SAN ,则可使用绑定挂载。绑定挂载更依赖于 Docker 主机的文件系统布局,但在许多状况下性能更高。下面的示例将主机的 /mnt/registry
目录绑定到 registry 容器的 /var/lib/registry/
目录中。
$ docker run -d \
-p 5000:5000 \ --restart=always \ --name registry \ -v /mnt/registry:/var/lib/registry \ registry:2
默认状况下,registry 将其数据存储在本地文件系统中,不管你是使用绑定挂载仍是使用卷。可使用 存储驱动程序 将 registry 数据存储在 Amazon S3 bucket,Google Cloud Platform 或其余存储后端中。更多信息,请参阅 存储配置选项。
运行仅在本地主机上可访问的 registry 具备有限的用处。为了使你的 registry 可以被外部主机访问,必须先开启 TLS。
下面的示例在下一小节 运行 registry 做为服务 中进行了扩展。
这些例子假设以下:
https://myregistry.domain.com/
。若是你已得到中间证书,请参阅本小节最后一部分 使用中间证书。
$ mkdir -p certs
将 .crt
和 .key
文件从 CA 复制到 certs
目录中。如下步骤假定这些文件被命名为 domain.crt
和 domain.key
。
$ docker container stop registry
指示 registry 使用 TLS 证书。该命令将 certs/
目录绑定到容器中的 /cert/
目录,并设置环境变量来告诉容器在哪里找到 domain.crt
和 domain.key
文件。registry 在端口 443 上运行,即默认的 HTTPS 端口。
$ 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 myregistry.domain.com/my-ubuntu
$ docker push myregistry.domain.com/my-ubuntu
$ docker pull myregistry.domain.com/my-ubuntu
证书颁发者可能会提供中间证书。在这种状况下,必须将你的证书与中间证书链接起来造成一个证书包(certificate bundle)。可使用 cat
命令执行此操做:
cat domain.crt intermediate-certificates.pem > certs/domain.crt
就像在前面的示例中使用 domain.crt
文件同样,可使用 certificate bundle。
registry 支持使用 Let’s Encrypt 自动获取浏览器信任的证书。有关 Let’s Encrypt 的更多信息,请参阅 https://letsencrypt.org/how-it-works/ 和 registry 配置 的相关部分。
可使用自签名证书,或者不安全地使用 registry。除非你已为自签名证书设置验证,不然这仅用于测试。请参阅 运行不安全的注册表。
Swarm 服务 相对于独立容器有几个优点。他们使用声明式模型(declarative model),这意味着你定义了所需的状态,而且 Docker 可使你的服务保持在该状态。服务提供自动负载均衡扩展,以及控制服务分布的能力等优点。服务还容许你在 secrets 中存储敏感数据,例如 TLS 证书。
你使用的存储后端决定你是使用彻底伸缩的服务仍是仅使用单个节点或节点约束的服务。
如下示例将 registry 做为单副本服务启动,该服务可经过任何 swarm 节点的 80 端口访问。假定你使用的是与前面示例中相同的 TLS 证书。
首先,将 TLS 证书和密钥保存为 secrets:
$ docker secret create domain.crt certs/domain.crt $ docker secret create domain.key certs/domain.key
接下来,将标签添加到要运行 registry 的节点。可使用 docker node ls
获取节点的名称。用下面的 node1
替换节点的名称。
$ docker node update --label-add registry=true node1
而后建立服务,授予其访问这两个 secrets 的权限,并将其限制为仅在具备标签 registry=true
的节点上运行。除了约束以外,还指定一次只能运行一个副本。该示例将 swarm 节点上的 /mnt/registry
绑定挂载到容器中的 /var/lib/registry/
。绑定挂载依赖于预先存在的源目录,所以确保 node1
上存在 /mnt/registry
。在运行如下 docker service create
命令以前,可能须要建立它。
默认状况下,secrets 在 /run/secrets/<secret-name>
处挂载到服务中。
$ docker service create \
--name registry \ --secret domain.crt \ --secret domain.key \ --constraint 'node.labels.registry==true' \ --mount type=bind,src=/mnt/registry,dst=/var/lib/registry \ -e REGISTRY_HTTP_ADDR=0.0.0.0:80 \ -e REGISTRY_HTTP_TLS_CERTIFICATE=/run/secrets/domain.crt \ -e REGISTRY_HTTP_TLS_KEY=/run/secrets/domain.key \ --publish published=80,target=80 \ --replicas 1 \ registry:2
能够访问任何 swarm 节点的 80 端口上的服务。Docker 将请求发送到正在运行该服务的节点。
人们可能想要使用负载均衡器分配负载,终止 TLS 或提供高可用性。虽然完整的负载均衡设置不在本文档的范围内,但有一些注意事项可使该过程更加流畅。
最重要的方面是,负载均衡的 registry 集群必须共享相同的资源。对于当前版本的 registry,这意味着如下内容必须相同:
上述任何差别都会致使服务请求出现问题。例如,若是使用的是文件系统驱动程序,则全部 registry 实例都必须可以访问同一台计算机上的相同文件系统根目录。对于其余驱动程序(如 S3 或 Azure),它们应该访问相同的资源并共享相同的配置。HTTP Secret 协调上传(The HTTP Secret coordinates uploads),跨实例也必须相同。能够配置不一样的 redis 实例(编写本文时),但若是实例不共享,则不是最优的,由于此时会致使更多的请求发送到后端服务器而不是使用 redis 缓存。
正确获取 header 很是重要。对于“/v2/”地址空间下的任何请求的全部响应,即便是 4xx 响应,Docker-Distribution-API-Version
的 header 也应设置为值“registry/2.0”。若是须要,此头容许 docker 引擎快速解析身份验证提示信息并回退到版本 1 的registry。确认此设置是否正确能够帮助避免回退问题。(This header allows the docker engine to quickly resolve authentication realms and fallback to version 1 registries, if necessary. Confirming this is setup correctly can help avoid problems with fallback.)
在一样的思路中,你必须确保正确地将 X-Forwarded-Proto
,X-Forwarded-For
和 Host
header 发送到它们的“客户端”值。若是不这样作,一般会使 registry 问题重定向到内部主机名或从 https 降级到 http。(Failure to do so usually makes the registry issue redirects to internal hostnames or downgrading from https to http.)
当“/v2/”端点在没有凭证的状况下被访问时,正确安全的 registry 应返回 401。响应应包含 WWW-Authenticate
,为如何进行身份验证提供指导,例如使用基自己份验证或令牌服务。若是负载平衡器有健康检查,建议将其配置为将 401 响应视为健康情况,其余状况视为关闭。经过确保认证的配置问题不会意外暴露未受保护的 registry,能够确保安全。若是你使用的是不太复杂的负载平衡器(例如亚马逊的 Elastic Load Balancer),它不容许更改健康的响应代码,则健康检查能够定向到“/”,它老是返回 200 OK
响应。
除了在安全的本地网络上运行的 registry 外,应始终对 registry 实施访问限制。
实现访问限制的最简单方法是经过基本认证(相似于其余 Web 服务器的基本认证机制)。这个例子使用经过 htpasswd
来存储 secrets 的原生基自己份认证。
警告:没法使用以纯文本格式发送凭证的身份验证方案进行身份验证。必须首先配置 TLS 才能使验证生效。
$ mkdir auth
$ docker run \
--entrypoint htpasswd \
registry:2 -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
在第一步提供用户名和密码。
测试如今能够从 registry 中获取镜像或将镜像推送到 registry。
X509 错误:X509 错误一般代表你正在尝试使用自签名证书,但未正确配置 Docker 守护程序。请参阅 运行不安全的注册表。
你可能但愿经过在 registry 前使用代理来实现更高级的基自己份验证。见 recipes 列表。
注册表还支持委派认证(delegated authentiation),将用户重定向到特定的可信令牌服务器(token server)。这种方法设置起来更加复杂,只有在须要彻底配置 ACL 并须要更多控制 registry 与全局受权和身份验证系统的集成时才有意义(only makes sense if you need to fully configure ACLs and need more control over the registry’s integration into your global authorization and authentication systems)。请参阅如下 背景信息 和 配置信息。
这种方法须要你使用本身的或第三方认证系统。
若是 registry 很复杂,那么使用 Docker compose 文件来部署它可能更容易,而不是依赖于特定的 docker run
调用。使用如下示例 docker-compose.yml
做为模板。
registry:
restart: always
image: registry:2
ports:
- 5000: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
将 /path
替换为包含 certs/
和 auth/
目录的目录。
经过在包含 docker-compose.yml
文件的目录中发出如下命令来启你的 registry:
$ docker-compose up -d
能够在没有互联网链接的环境中运行 registry。可是,若是你依赖任何非本地镜像,则须要考虑如下几点:
docker pull
以获取远程可用的任何镜像,而后将 registry 的数据卷迁移到隔离网络(air-gapped network)。在 Docker 17.06 及更高版本中,能够配置 Docker 守护程序,以容许在这种状况下将不可分配的层上传到私有 registry。这仅适用于存在不可分配镜像的空隙设置或带宽极端有限的状况下。你有责任确保你符合不可分配的层的使用条款。
/etc/docker/
和 Windows Server 上的 C:\ProgramData\docker\config\daemon.json
中的 daemon.json
文件。假设文件先前为空,请添加如下内容:{
"allow-nondistributable-artifacts": ["myregistrydomain.com:5000"] }
值是 registry 地址数组,用逗号分隔。
保存并退出。
警告:不可分发的构件一般对如何以及在何处分发和共享有限制。只有使用此功能才能将工件推送到私有 registry,并确保你符合包含从新分配不可分配构件的任何条款。