如何在 Ubuntu 14.04 上设置私有 Docker 注册表

介绍

Docker是部署您的服务器的绝佳工具。Docker甚至有一个名为Docker Hub的公共注册表来存储Docker图像。Docker允许您免费上传您的Docker创作到他们的Docker Hub,但您上传的任何东西都是公共的。

本指南将向您展示如何设置和保护您自己的私人Docker注册表. 在本教程的结束时,您将能够将自定义的Docker图像推到您的私人注册表并安全地从不同的主机中提取图像。

本教程不涵盖容器化自己的应用程序,而只是如何创建可以存储部署的注册表. 如果您想了解如何开始使用 Docker 本身(而不是注册表),您可能想阅读 如何安装和使用 Docker:开始教程。

本教程已与运行Ubuntu 14.04**的注册表服务器和注册表客户端进行测试,但它可能与其他基于Debian的发行版一起工作。

Docker 概念

如果你以前还没有使用Docker,那么花一分钟的时间来了解一些Docker的关键概念. 如果你已经使用Docker,只想知道如何开始运行自己的注册表,那么请跳过到下一节。

对于如何使用 Docker 的更新,请查看优秀的 Docker Cheat Sheet

Docker 核心是将应用程序和运行它所需的依赖性从操作系统本身分离出来的一种方法. 为了实现这一点,Docker 使用 containersimages。 Docker 图像基本上是文件系统的模板。 当您运行 Docker 图像时,该文件系统的实例会生动并在您的系统上运行,并且在 Docker 容器内运行。 默认情况下,此容器无法触及原始图像本身或运行 Docker 的主机的文件系统。

如果你决定要保留这些更改,那么你可以承诺一个集装箱到一个Docker图像(通过Docker Commit命令)。这意味着你可以生成新的集装箱,从你的旧集装箱的内容开始,而不会影响原始集装箱(或图像)。

为了继续类比,运行私人Docker注册表就像为您的Docker图像运行私人Git存储库。

前提条件

要完成本教程,您将需要以下内容:

步骤 1 – 安装附加安全性包

为了为 Docker 注册表设置安全性,最好使用 Docker Compose。这样,我们可以轻松地在一个容器中运行 Docker 注册表,并让 Nginx 在另一个容器中处理安全性和与外部世界的通信。

由于我们将使用 Nginx 来处理我们的安全,我们还需要一个地方来存储我们想要访问注册表的用户名和密码组合列表。

1sudo apt-get -y install apache2-utils

步骤 2 – 安装和配置 Docker 注册表

Docker 命令行工具非常适合启动和管理一个或两个 Docker 容器,但大多数在 Docker 容器内运行的应用程序并不存在单独。要完全部署大多数应用程序,您需要几个组件并行运行,例如,大多数 Web 应用程序由提供应用程序代码的 Web 服务器、PHP 或 Ruby (与 Rails) 等解读脚本语言和 MySQL 等数据库服务器组成。

Docker Compose 允许您为每个容器编写一个.yml 配置文件,以及有关容器如何相互通信的信息。

由于Docker注册表本身是一个具有多个组件的应用程序,我们将使用Docker Compose来管理我们的配置。

要启动一个基本注册表,唯一需要的配置是定义您的注册表将存储其数据的位置. 让我们设置一个基本的 Docker Compose YAML 文件来创建一个基本的注册表实例。

首先,创建一个文件夹,我们为本教程的文件将生活和我们需要的一些子文件夹:

1mkdir ~/docker-registry && cd $_
2mkdir data

使用您最喜欢的文本编辑器,创建一个 docker-compose.yml 文件:

1nano docker-compose.yml

将以下内容添加到文件中:

1[label docker-compose.yml]
2registry:
3  image: registry:2
4  ports:
5    - 127.0.0.1:5000:5000
6  environment:
7    REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
8  volumes:
9    - ./data:/data

环境部分中,Docker 注册表容器中设置了一个环境变量,其路径是/data。Docker 注册表应用程序知道在启动时检查此环境变量,并开始将其数据保存到/data文件夹。

只有在这种情况下,卷: -. / 数据: / 数据的比特会告诉Docker,该容器中的 / 数据目录实际上应该在我们的主机上绘制到 / 数据

让我们继续前进并开始,以确保一切顺序:

1cd ~/docker-registry
2docker-compose up

您将看到一堆下载栏在屏幕上移动(这是Docker从Docker自己的Docker注册表中下载的实际Docker注册表图像)。

1[secondary_label Output of docker-compose up]
2registry_1 | time="2015-10-18T23:45:58Z" level=warning msg="No HTTP secret provided - generated random secret. This may cause problems with uploads if multiple registries are behind a load-balancer. To provide a shared secret, fill in http.secret in the configuration file or set the REGISTRY_HTTP_SECRET environment variable." instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
3registry_1 | time="2015-10-18T23:45:58Z" level=info msg="redis not configured" instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
4registry_1 | time="2015-10-18T23:45:58Z" level=info msg="using inmemory blob descriptor cache" instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
5registry_1 | time="2015-10-18T23:45:58Z" level=info msg="listening on [::]:5000" instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
6registry_1 | time="2015-10-18T23:45:58Z" level=info msg="Starting upload purge in 1m0s" instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1

不要担心没有提供HTTP秘密消息,这是正常的。

很棒! 在这一点上,你已经有了完整的Docker注册表,并在端口5000上运行并聆听(这是在Docker-compose.yml文件中的端口:小块设置的)。

默认情况下,Docker Compose 将永远等待您的输入,所以继续按CTRL-C关闭您的Docker注册表容器。

步骤 3 – 设置一个 Nginx 容器

第一步是在另一个 Docker 容器内设置 Nginx 副本,并将其链接到我们的 Docker 注册表容器。

让我们先创建一个目录来存储我们的 Nginx 配置:

1mkdir ~/docker-registry/nginx

现在,在~/docker-registry目录中重新打开您的docker-compose.yml文件:

1nano docker-compose.yml

将下列内容插入文件的顶部:

1[label docker-compose.yml]
2nginx:
3  image: "nginx:1.9"
4  ports:
5    - 5043:443
6  links:
7    - registry:registry
8  volumes:
9    - ./nginx/:/etc/nginx/conf.d:ro

这将基于官方 Nginx 图像创建一个新的 Docker 容器. 这里的有趣点是链接部分. 它自动设置了一个链接从一个 Docker 容器到另一个。 当 Nginx 容器启动时,它将能够到达主机名注册表上的注册表容器,无论注册表容器最终拥有什么实际的 IP 地址(在场景背后,Docker 实际上在nginx容器中插入/etc/hosts文件,告诉它注册表容器的 IP)。

卷:部分类似于我们对注册表容器所做的。在这种情况下,它为我们提供了存储我们将在主机上使用的 Nginx 配置文件的方式,而不是在 Docker 容器内部。

您的完整的 'docker-compose.yml' 文件现在应该是这样的:

 1[label docker-compose.yml]
 2nginx:
 3  image: "nginx:1.9"
 4  ports:
 5    - 5043:443
 6  links:
 7    - registry:registry
 8  volumes:
 9    - ./nginx/:/etc/nginx/conf.d
10registry:
11  image: registry:2
12  ports:
13    - 127.0.0.1:5000:5000
14  environment:
15    REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
16  volumes:
17    - ./data:/data

运行docker-compose up将同时启动两个容器:一个用于Docker注册表和一个用于Nginx。

我们需要配置 Nginx 才能做到这一点,所以让我们创建一个新的 Nginx 配置文件。

创建一个 Registry.conf 文件:

1nano ~/docker-registry/nginx/registry.conf

将下列内容复制到文件中:

 1[label ~/docker-registry/nginx/registry.conf]
 2upstream docker-registry {
 3  server registry:5000;
 4}
 5
 6server {
 7  listen 443;
 8  server_name myregistrydomain.com;
 9
10  # SSL
11  # ssl on;
12  # ssl_certificate /etc/nginx/conf.d/domain.crt;
13  # ssl_certificate_key /etc/nginx/conf.d/domain.key;
14
15  # disable any limits to avoid HTTP 413 for large image uploads
16  client_max_body_size 0;
17
18  # required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
19  chunked_transfer_encoding on;
20
21  location /v2/ {
22    # Do not allow connections from docker 1.5 and earlier
23    # docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents
24    if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
25      return 404;
26    }
27
28    # To add basic authentication to v2 use auth_basic setting plus add_header
29    # auth_basic "registry.localhost";
30    # auth_basic_user_file /etc/nginx/conf.d/registry.password;
31    # add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;
32
33    proxy_pass http://docker-registry;
34    proxy_set_header Host              $http_host;   # required for docker client's sake
35    proxy_set_header X-Real-IP         $remote_addr; # pass on real client's IP
36    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
37    proxy_set_header X-Forwarded-Proto $scheme;
38    proxy_read_timeout 900;
39  }
40}

保存和退出文件。

现在你可以安装 Nginx 并使用一个命令启动两个 Docker 容器:

1docker-compose up

Nginx在启动时没有打印任何输出,但如果一切顺利,你现在正在运行一个 Nginx 副本,该副本已设置为代理到你的注册表容器。 为了测试它,让我们使用弯曲来直接向我们的 Docker 注册表发送 HTTP 请求,然后向我们的 Nginx 端口发送另一个请求。

首先,直接向 Docker 注册表提出 HTTP 请求:

1curl http://localhost:5000/v2/

Docker 返回一个空的 json 对象,所以你应该看到:

1[secondary_label Output]
2{}

现在将 HTTP 请求发送到 Nginx 端口:

1curl http://localhost:5043/v2/

你应该看到相同的结果:

1[secondary_label Output]
2{}

如果事情正常工作,你会在你的docker-compose终端中看到一些输出,它也看起来像下面:

1[secondary_label Output of docker-compose]
2    registry_1 | time="2015-08-11T10:24:53.746529894Z" level=debug msg="authorizing request" environment=development http.request.host="localhost:5043" http.request.id=55c3e2a6-4f34-4b0b-bc57-11c814b4f4d3 http.request.method=GET http.request.remoteaddr=172.17.42.1 http.request.uri="/v2/" http.request.useragent="curl/7.35.0" instance.id=55634dfc-c9e0-4ec9-9872-6f4930c17759 service=registry version=v2.0.1
3    registry_1 | time="2015-08-11T10:24:53.747650205Z" level=info msg="response completed" environment=development http.request.host="localhost:5043" http.request.id=55c3e2a6-4f34-4b0b-bc57-11c814b4f4d3 http.request.method=GET http.request.remoteaddr=172.17.42.1 http.request.uri="/v2/" http.request.useragent="curl/7.35.0" http.response.contenttype="application/json; charset=utf-8" http.response.duration=8.143193ms http.response.status=200 http.response.written=2 instance.id=55634dfc-c9e0-4ec9-9872-6f4930c17759 service=registry version=v2.0.1
4    registry_1 | 172.17.0.21 - - [11/Aug/2015:10:24:53 +0000] "GET /v2/ HTTP/1.0" 200 2 "" "curl/7.35.0"
5    nginx_1    | 172.17.42.1 - - [11/Aug/2015:10:24:53 +0000] "GET /v2/ HTTP/1.1" 200 2 "-" "curl/7.35.0" "-"

如果您看到带有registry_前缀的行(在您的机器上_后的数字可能不同),那么一切都很好, Nginx 已成功将我们的 HTTP 请求代理到 Docker 注册表。

继续,在您的docker-compose终端中再次按CTRL-C,以关闭您的Docker容器。

步骤4:设置身份验证

现在 Nginx 正在正确地代理请求,让我们用 HTTP 身份验证来设置它,这样我们就可以控制谁可以访问我们的 Docker 注册表。

创建第一位用户如下,用您想要使用的用户名取代 USERNAME:

1cd ~/docker-registry/nginx
2htpasswd -c registry.password USERNAME

当被提示时为该用户创建一个新的密码。

如果您想在未来添加更多用户,只需重新运行上述命令而无需选项-c(c用于创建):

1htpasswd registry.password USERNAME

在此时,我们有一个registry.password文件,我们的用户设置和一个可用的Docker注册表. 如果您想查看您的用户,您可以随时查看该文件(如果您想要撤销访问,则可以删除用户)。

接下来,我们需要告诉 Nginx 使用该身份验证文件。

在您最喜欢的文本编辑器中打开 ~/docker-registry/nginx/registry.conf:

1nano ~/docker-registry/nginx/registry.conf

滚动到文件的中间,你会看到一些看起来像这样的行:

1[label ~/docker-registry/nginx/registry.conf]
2# To add basic authentication to v2 use auth_basic setting plus add_header
3# auth_basic "registry.localhost";
4# auth_basic_user_file /etc/nginx/conf.d/registry.password;
5# add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;

通过删除字符#在线的开始 的两行,以auth_basic开头,以及以add_header开头的行。

1[label ~/docker-registry/nginx/registry.conf]
2# To add basic authentication to v2 use auth_basic setting plus add_header
3auth_basic "registry.localhost";
4auth_basic_user_file /etc/nginx/conf.d/registry.password;
5add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;

我们现在告诉 Nginx 启用所有向 Docker 注册表代理的请求的 HTTP 基本身份验证,并告诉它使用我们刚刚创建的密码文件。

让我们把我们的容器拿回来看看身份验证是否起作用:

1cd ~/docker-registry
2docker-compose up

重复上一次的Curl测试:

1curl http://localhost:5043/v2/

您应该收到一个抱怨未经授权的消息:

1[secondary_label Output of curl]
2<html>
3<head><title>401 Authorization Required</title></head>
4<body bgcolor="white">
5<center><h1>401 Authorization Required</h1></center>
6<hr><center>nginx/1.9.7</center>
7</body>
8</html>

现在尝试将您之前创建的用户名和密码添加到弯曲请求中:

1curl http://USERNAME:PASSWORD@localhost:5043/v2/

您应该在docker-compose终端中看到相同的registry_输出。

继续使用docker-compose终端中的CTRL-C来关闭 Docker 容器。

步骤五:设置SSL

在此时刻,我们有注册表在 Nginx 后面运行,HTTP 基本身份验证工作. 然而,设置仍然不太安全,因为连接没有加密。

首先,打开 Nginx 配置文件进行编辑:

1nano ~/docker-registry/nginx/registry.conf

使用箭头键移动并寻找这些行:

1[label ~/docker-registry/nginx/registry.conf]
2server {
3  listen 443;
4  server_name myregistrydomain.com;
5
6  # SSL
7  # ssl on;
8  # ssl_certificate /etc/nginx/conf.d/domain.crt;
9  # ssl_certificate_key /etc/nginx/conf.d/domain.key;

如果您为您的服务器设置了域名,请在您完成时将server_name值更改为您的域名。

1[label ~/docker-registry/nginx/registry.conf]
2server {
3  listen 443;
4  server_name myregistrydomain.com;
5
6  # SSL
7  ssl on;
8  ssl_certificate /etc/nginx/conf.d/domain.crt;
9  ssl_certificate_key /etc/nginx/conf.d/domain.key;

Nginx现在已配置使用SSL,并将搜索SSL证书和关键文件在/etc/nginx/conf.d/domain.crt/etc/nginx/conf.d/domain.key respectively. 由于我们早些时候在我们的docker-compose.yml文件中设置的地图, Nginx容器中的/etc/nginx/conf.d/路径与我们主机上的~/docker-registry/nginx/文件夹相匹配,所以我们会把我们的证书文件放在那里。

如果您已经设置了SSL证书或计划购买一个,那么您可以简单地将证书和密钥文件复制到registry.conf(ssl_certificatessl_certificate_key)中列出的路径。

您也可以获得 免费签名的SSL证书

否则,我们将不得不使用自签名的SSL证书。

签署自己的证书

由于Docker目前不允许您使用自签名的SSL证书,这比通常更为复杂 - 我们还必须设置我们的系统来作为我们自己的证书签名机构。

首先,让我们更改到我们的 `~/docker-registry/nginx’ 文件夹,并准备创建证书:

1cd ~/docker-registry/nginx

创建一个新的 root 密钥:

1openssl genrsa -out devdockerCA.key 2048

生成根证书(在提示中输入您想要的任何内容):

1openssl req -x509 -new -nodes -key devdockerCA.key -days 10000 -out devdockerCA.crt

然后为您的服务器生成一个密钥(这是我们 Nginx 配置中的 ssl_certificate_key 引用的文件):

1openssl genrsa -out domain.key 2048

现在我们必须提出签署证书的申请。

输入此命令后,OpenSSL 会提示你回答几个问题. 写下你想要的任何东西,但当OpenSSL 要求你输入 共同名称时,请确保输入你的服务器的域名或 IP

1openssl req -new -key domain.key -out dev-docker-registry.com.csr

例如,如果您的 Docker 注册表将运行在域名 **www.ilovedocker.com**上,则您的输入应该是这样的:

 1Country Name (2 letter code) [AU]:
 2State or Province Name (full name) [Some-State]:
 3Locality Name (eg, city) []:
 4Organization Name (eg, company) [Internet Widgits Pty Ltd]:
 5Organizational Unit Name (eg, section) []:
 6Common Name (e.g. server FQDN or YOUR name) []:www.ilovedocker.com
 7Email Address []:
 8
 9Please enter the following 'extra' attributes
10to be sent with your certificate request
11A challenge password []:
12An optional company name []:

不要输入挑战密码。

接下来,我们需要签署证书申请:

1openssl x509 -req -in dev-docker-registry.com.csr -CA devdockerCA.crt -CAkey devdockerCA.key -CAcreateserial -out domain.crt -days 10000

由于我们刚刚生成的证书没有被任何已知的证书授权机构(例如,VeriSign)验证,我们需要告诉任何将使用Docker注册表的客户端,这是一个合法的证书。

1sudo mkdir /usr/local/share/ca-certificates/docker-dev-cert
2sudo cp devdockerCA.crt /usr/local/share/ca-certificates/docker-dev-cert
3sudo update-ca-certificates

重新启动 Docker 示范器,以便将更改收集到我们的证书商店:

1sudo service docker restart

<$>[警告] 警告: 您将不得不对连接到此Docker注册表的每个机器重复此步骤! 对于Ubuntu 14.04客户端来说,如何做到这一点的说明列在 Step 9 — Accessing Your Docker Registry from a Client Machine 中。

第6步:测试SSL

带上我们的Docker容器,通过现在熟悉的docker-compose up:

1cd ~/docker-registry
2docker-compose up

从另一个终端进行另一个弯曲测试(仅此时使用HTTPS),以验证我们的SSL设置是否正常工作. 请记住,为了SSL正确工作,您将不得不使用您之前在创建SSL证书时在共同名称字段中输入的相同域名。

1curl https://USERNAME:PASSWORD@[YOUR-DOMAIN]:5043/v2/

<$>[注] 注: 如果您正在使用自签证书,则会看到以下错误从 curl:

1curl: (60) SSL certificate problem: self signed certificate

使用 -k 选项告诉 curl not 与同行进行验证:

1curl -k https://USERNAME:PASSWORD@[YOUR-DOMAIN]:5043/v2/

美元

例如,如果您设置的用户和密码为sammytest,并且您的SSL证书为www.example.com,则您会输入以下内容:

1curl https://sammy:[email protected]:5043/v2/

如果一切顺利,弯曲将打印一个空的 json 对象{},你的docker-compose终端将打印通常的registry_输出。

如果没有,请重新检查SSL步骤和您的Nginx配置文件,以确保一切都正确。

在这一点上,我们有一个功能的Docker注册表 2.0,并在Nginx服务器背后运行,该服务器通过SSL提供身份验证和加密。如果您的防火墙已配置为允许从外部访问端口 5043',那么您应该能够从任何机器登录这个Docker注册表 docker login https://`并输入您在上一节设置的用户名和密码。

步骤7:将SSL端口设置为443

在完成之前,只需要做几步:更改端口以使用标准SSL端口443(可选),并设置docker-compose,以便在启动时启动此集合容器。

让我们先设置我们的Dockered Nginx容器来倾听端口443(SSL的标准端口),而不是我们迄今为止使用的非标准端口5043. 1024以下的端口在Linux上是特权端口,这意味着我们将不得不运行我们的docker-compose容器作为根。

首先在文本编辑器中打开docker-compose.yml:

1nano ~/docker-registry/docker-compose.yml

在 Nginx 部分中,你会看到一个 port: 部分,更改 - 5043:443 行(这将我们的主机上的端口 5043 地图到 Nginx 容器内部的端口 443)到 `- 443:443',以便我们的 Nginx 容器的端口 443 被映射到我们的主机的端口 443。

 1[label ~/docker-registry/docker-compose.yml]
 2nginx:
 3  image: "nginx:1.9"
 4  ports:
 5    - 443:443
 6  links:
 7    - registry:registry
 8  volumes:
 9    - ./nginx/:/etc/nginx/conf.d:ro
10registry:
11  image: registry:2
12  ports:
13    - 127.0.0.1:5000:5000
14  environment:
15    REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
16  volumes:
17    - ./data:/data

如果仍在运行,请通过 CTRL-C 杀死您的docker-compose会话,然后在端口 443 重新启动它:

1sudo docker-compose up

<$>[注] 注: 只有根用户可以听到1024以下的端口。请注意,您需要使用sudo这个时候与docker-compose命令,以便 Nginx 可以在默认 SSL 端口 443 上运行。

你应该看到docker-compose像往常一样开始。

让我们尝试使用我们的域名另一个弯曲测试,但这次我们不会在URL中指定:5043:

1curl https://<YOURUSERNAME>:<YOURPASSWORD>@YOUR-DOMAIN/v2/

如果一切顺利,你应该在你的docker-compose终端中看到通常的registry_输出,你也可能想尝试从另一台机器运行同样的curl命令,以确保你的端口443暴露在外部世界。

继续使用 CTRL-Cdocker-compose 终端关闭 Docker 容器,然后转到下一步。

步骤 8 — 启动 Docker 注册表作为服务

如果一切看起来都很好,让我们继续创建一个 Upstart脚本,以便我们的Docker注册表每次启动时都启动。

首先,让我们删除任何现有容器,将我们的Docker注册表移动到整个系统的位置,并更改其对根的权限:

1cd ~/docker-registry
2docker-compose rm   # this removes the existing containers 
3sudo mv ~/docker-registry /docker-registry
4sudo chown -R root: /docker-registry

然后使用您最喜欢的文本编辑器创建一个Upstart脚本:

1sudo nano /etc/init/docker-registry.conf

添加以下内容来创建 Upstart 脚本(让 Upstart 正确监控 Docker 容器有点麻烦,请查看 本博客帖子如果您想要更多关于这个 Upstart 脚本正在做的事情的信息):

 1[label /etc/init/docker-registry.conf]
 2description "Docker Registry"
 3
 4start on runlevel [2345]
 5stop on runlevel [016]
 6
 7respawn
 8respawn limit 10 5
 9
10chdir /docker-registry
11
12exec /usr/local/bin/docker-compose up

有关 Upstart 脚本的更多信息,请阅读 此教程

让我们通过运行测试我们的新Upstart脚本:

1sudo service docker-registry start

你应该看到这样的东西:

1docker-registry start/running, process 25303

您可以通过执行以下操作来验证服务器是否正在运行:

1docker ps

输出应类似于下列情况(请注意,所有名称都以dockerregistry_开头)

1CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2d4b6fef0b4d1 nginx:1.9           "nginx -g 'daemon of 2 minutes ago Up 2 minutes 80/tcp, 0.0.0.0:443->443/tcp dockerregistry_nginx_1
377668352bd39 registry:2          "registry cmd/regist 2 minutes ago Up 2 minutes 127.0.0.1:5000->5000/tcp dockerregistry_registry_1

Upstart将登录docker-compose命令的输出到/var/log/upstart/docker-registry.log 对于我们的最终测试,让我们live-watchtail的日志文件(sudo是必要的,因为 upstart日志被写成根用户):

1sudo tail -f /var/log/upstart/docker-registry.log

从另一个终端或机器前进并运行我们现在熟悉的弯曲测试:

1curl https://<YOUR_USERNAME>:<YOURPASSWORD>@[YOUR-DOMAIN]/v2/

如果一切正常工作,弯曲将打印一个{}到您的终端,你应该看到通常的:

1registry_1 | time="2015-08-12T08:01:12.241887501Z" level=debug msg="authorizing request" environment=development http.request.host=docker.meatflavoredbeer.com http.request.id=e8d69e16-9448-4c48-afd8-57b1f1302742 http.request.method=GET http.request.remoteaddr=106.1.247.4 http.request.uri="/v2/" http.request.useragent="curl/7.37.1" instance.id=14d4727b-fda1-463f-8d0e-181f4c70cb17 service=registry version=v2.0.1
2registry_1 | time="2015-08-12T08:01:12.242206499Z" level=info msg="response completed" environment=development http.request.host=docker.meatflavoredbeer.com http.request.id=e8d69e16-9448-4c48-afd8-57b1f1302742 http.request.method=GET http.request.remoteaddr=106.1.247.4 http.request.uri="/v2/" http.request.useragent="curl/7.37.1" http.response.contenttype="application/json; charset=utf-8" http.response.duration=3.359883ms http.response.status=200 http.response.written=2 instance.id=14d4727b-fda1-463f-8d0e-181f4c70cb17 service=registry version=v2.0.1
3registry_1 | 172.17.0.4 - - [12/Aug/2015:08:01:12 +0000] "GET /v2/ HTTP/1.0" 200 2 "" "curl/7.37.1"
4nginx_1    | 106.1.247.4 - nik [12/Aug/2015:08:01:12 +0000] "GET /v2/ HTTP/1.1" 200 2 "-" "curl/7.37.1" "-"

步骤 9 – 从客户机访问您的 Docker 注册表

若要从另一台机器访问您的 Docker 注册表,请先将您之前创建的 SSL 证书添加到新客户端机器中,您想要的文件位于 ~/docker-registry/nginx/devdockerCA.crt

您可以直接将其复制到新机器,或者使用下面的说明来复制和粘贴:

注册表服务器上,查看证书:

1sudo cat /docker-registry/nginx/devdockerCA.crt

你会得到一个看起来像这样的输出:

 1[secondary_label Output of sudo cat /docker-registry/nginx/devdockerCA.crt]
 2-----BEGIN CERTIFICATE-----
 3MIIDXTCCAkWgAwIBAgIJANiXy7fHSPrmMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
 4BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
 5aWRnaXRzIFB0eSBMdGQwHhcNMTQwOTIxMDYwODE2WhcNNDIwMjA2MDYwODE2WjBF
 6MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
 7ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
 8CgKCAQEAuK4kNFaY3k/0RdKRK1XLj9+IrpR7WW5lrNaFB0OIiItHV9FjyuSWK2mj
 9ObR1IWJNrVSqWvfZ/CLGay6Lp9DJvBbpT68dhuS5xbVw3bs3ghB24TntDYhHMAc8
10GWor/ZQTzjccHUd1SJxt5mGXalNHUharkLd8mv4fAb7Mh/7AFP32W4X+scPE2bVH
11OJ1qH8ACo7pSVl1Ohcri6sMp01GoELyykpXu5azhuCnfXLRyuOvQb7llV5WyKhq+
12SjcE3c2C+hCCC5g6IzRcMEg336Ktn5su+kK6c0hoD0PR/W0PtwgH4XlNdpVFqMST
13vthEG+Hv6xVGGH+nTszN7F9ugVMxewIDAQABo1AwTjAdBgNVHQ4EFgQULek+WVyK
14dJk3JIHoI4iVi0FPtdwwHwYDVR0jBBgwFoAULek+WVyKdJk3JIHoI4iVi0FPtdww
15DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkignESZcgr4dBmVZqDwh
16YsrKeWSkj+5p9eW5hCHJ5Eg2X8oGTgItuLaLfyFWPS3MYWWMzggxgKMOQM+9o3+k
17oH5sUmraNzI3TmAtkqd/8isXzBUV661BbSV0obAgF/ul5v3Tl5uBbCXObC+NUikM
18O0C3fDmmeK799AM/hP5CTDehNaFXABGoVRMSlGYe8hZqap/Jm6AaKThV4g6n4F7M
19u5wYtI9YDMsxeVW6OP9ZfvpGZW/n/88MSFjMlBjFfFsorfRd6P5WADhdfA6CBECG
20LP83r7/MhqO06EOpsv4n2CJ3yoyqIr1L1+6C7Erl2em/jfOb/24y63dj/ATytt2H
216g==
22-----END CERTIFICATE-----

将该输出复制到您的剪辑板,并连接到您的客户端机器。

在客户端机器上,创建证书目录:

1sudo mkdir /usr/local/share/ca-certificates/docker-dev-cert

打开证书文件进行编辑:

1sudo nano /usr/local/share/ca-certificates/docker-dev-cert/devdockerCA.crt

贴上证书内容。

通过查看文件来验证该文件是否正确保存到客户端机器:

1cat /usr/local/share/ca-certificates/docker-dev-cert/devdockerCA.crt

如果一切正常工作,你会看到以前的相同文本:

1[secondary_label Output of cat /usr/local/share/ca-certificates/docker-dev-cert/devdockerCA.crt]
2-----BEGIN CERTIFICATE-----
3MIIDXTCCAkWgAwIBAgIJANiXy7fHSPrmMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
4...
5...
6LP83r7/MhqO06EOpsv4n2CJ3yoyqIr1L1+6C7Erl2em/jfOb/24y63dj/ATytt2H
76g==
8-----END CERTIFICATE-----

现在更新证书:

1sudo update-ca-certificates

您应该得到的输出看起来如下(请注意1添加):

1[secondary_label Output of sudo update-ca-certificates]
2Updating certificates in /etc/ssl/certs... 1 added, 0 removed; done.
3Running hooks in /etc/ca-certificates/update.d....done.

如果您尚未在客户端上安装 Docker,请立即这样做(请参阅前提部分)。

重新启动 Docker 以确保它重新加载系统的 CA 证书。

1sudo service docker restart

您现在应该能够从客户端机器登录到您的 Docker 注册表:

1docker login https://YOUR-DOMAIN

请注意,您正在使用 https://. 输入您之前设置的用户名和密码(如果提示的话,输入任何您想要的电子邮件)。

1[secondary_label Output of docker login]
2Username: USERNAME
3Password: PASSWORD
4Email: 
5Account created. Please see the documentation of the registry http://localhost:5000/v1/ for instructions how to activate it.

你应该看到以下信息:

1[secondary_label Output of docker login]
2Login Succeeded

在此时刻,您的Docker注册表已启动并运行!让我们创建一个测试图像来推动注册表。

步骤 10 – 发布到您的私人 Docker 注册表

您现在已经准备好将图像发布到您的私人Docker注册表中,但首先我们必须创建一个图像,我们将根据Docker Hub的ubuntu图像创建一个简单的图像。

从您的 客户端机器,创建一个小空的图像来推到我们的新注册表。

1docker run -t -i ubuntu /bin/bash

完成下载后,你将进入Docker提示,让我们通过创建一个名为成功的文件来快速更改文件系统:

1touch /SUCCESS

退出 Docker 容器:

1exit

承诺改变:

1docker commit $(docker ps -lq) test-image

此命令会创建一个名为测试图像的新图像,基于已经运行的图像以及您所做的任何更改。

此图像目前仅存在于本地,所以让我们把它推到我们创建的新注册表中。

在之前的步骤中,您已登录到您的私人 Docker 注册表. 如果您尚未登录,请再次登录(请注意您想要使用 https://):

1docker login https://YOUR-DOMAIN

输入您之前设置的用户名和密码:

1Username: USERNAME
2Password: PASSWORD
3Email: 
4Account created. Please see the documentation of the registry http://localhost:5000/v1/ for instructions how to activate it.

Docker 有一个不寻常的机制来指定哪个注册表要点击. 你必须标记一个图像与私人注册表的位置,以便点击它. 让我们标记我们的图像到我们的私人注册表:

1docker tag test-image [YOUR-DOMAIN]/test-image

请注意,您首先使用图像的本地名称,然后是您想要添加的标签。标签不会使用https://,只使用域名、端口和图像名称。

现在我们可以将该图像推到我们的注册表. 这次我们只使用标签名称:

1docker push [YOUR-DOMAIN]/test-image

这将需要一段时间来上传到注册表服务器. 您应该看到输出以类似于下面的东西结束:

1[secondary_label Output of docker push]
2latest: digest: sha256:5ea1cfb425544011a3198757f9c6b283fa209a928caabe56063f85f3402363b4 size: 8008

步骤 11 – 从您的 Docker 注册表中提取

为了确保一切工作,让我们回到我们的原始服务器(在那里您安装了Docker注册表)并从客户端抽取我们刚刚推出的图像。

如果 Docker 未安装在测试引导服务器上,请从步骤 6 返回并遵循安装指示(如果是第三方服务器,则是 SSL 指示)。

使用您之前设置的用户名和密码登录。

1docker login https://[YOUR-DOMAIN]

你只想要标签图像名称,其中包括域名、端口和图像名称(但不是https://):

1docker pull [YOUR-DOMAIN]/test-image

如果你在新机器上运行图像,你会看到我们之前创建的SUCCESS文件在那里:

1docker run -t -i [YOUR-DOMAIN]/test-image /bin/bash

列出您的文件在 bash 壳中:

1ls

你应该看到我们之前为此图像创建的SUCCESS文件:

1SUCCESS bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var

结论

恭喜您!您刚刚使用自己的私人Docker注册表来推送和拉动您的第一个Docker容器!

快乐的Docker!

Published At
Categories with 技术
comments powered by Disqus