如何建立一个私人Docker登记在Ubuntu 14.04

发布,并从自己的私人Docker注册表拉Docker图像。

介绍

Docker是部署服务器一个伟大的工具。 Docker甚至有一个称为Docker Hub的公共注册表来存储Docker镜像。 虽然Docker允许您将Docker创建版本免费上传到他们的Docker Hub,但您上传的任何内容都是公开的。 这可能不是您项目的最佳选择。

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

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

本教程已经过测试,同时与注册服务器和运行Ubuntu 14.04注册表客户端,但它可能与其他基于Debian的发行工作。 它还涵盖版本2.0的Docker注册表。

Docker概念

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

有关如何使用Docker复习,看看优秀的Docker小抄

Docker的核心是一种分离应用程序和从操作系统本身运行它所需的依赖关系的方法。 为了实现这一目标Docker使用的容器图像 Docker镜像基本上是一个文件系统的模板。 当你运行一个Docker镜像时,这个文件系统的一个实例被激活,并在你的系统上运行一个Docker容器。 默认情况下,此容器不能接触原始映像本身或运行Docker的主机的文件系统。 这是一个自给自足的环境。

无论在容器中进行的任何更改都保留在容器本身中,并且不会影响原始图像。 如果您决定要保留这些变化,那么你就可以“提交”到Docker形象的容器(通过docker commit命令)。 这意味着您可以生成以旧容器的内容开头的新容器,而不会影响原始容器(或映像)。 如果你熟悉git ,那么工作流应该看起来颇为相似:您可以从任何容器中创建新的分行(位于Docker的说法图像)。 运行的图像有点像做了git checkout

要继续比较,运行私有Docker注册表就像为Docker镜像运行一个私有Git仓库。

先决条件

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

第1步 - 安装软件包以增加安全性

要设置Docker注册表安全,最好使用Docker Compose 这样我们可以轻松地在一个容器中运行Docker注册表,让Nginx在另一个容器中处理安全和与外部世界的通信。 您应该已经从先决条件部分安装它。

由于我们将使用Nginx来处理我们的安全,我们还需要一个地方来存储我们想要访问我们的注册表的用户名和密码组合的列表。 我们将安装apache2-utils包中包含htpasswd实用工具,可以很容易地生成密码哈希值的Nginx可以理解:

sudo apt-get -y install apache2-utils

第2步 - 安装和配置Docker注册表

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

Docker Compose可以让你写一个.yml为每个容器中的配置配置文件以及有关容器如何相互通信。 然后使用docker-compose命令行工具来发出命令到所有组成应用程序的组件。

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

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

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

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

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

nano docker-compose.yml

将以下内容添加到文件:

docker-compose.yml
registry:
  image: registry:2
  ports:
    - 127.0.0.1:5000:5000
  environment:
    REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
  volumes:
    - ./data:/data

这里有趣的是结束。 environment部分设置与路径Docker注册表容器中的环境变量/data Docker注册表应用程序知道在启动时检查此环境变量,并开始其数据保存到/data结果的文件夹。

只有在这种情况下, volumes: - ./data:/data位告诉泊坞的/data在该容器目录应该实际上映射到/data我们的主机上。 所以,最终的结果是,Docker注册表数据都被存储在~/docker-registry/data我们本地机器上。

让我们开始吧,以确保一切顺利:

cd ~/docker-registry
docker-compose up

你会看到一堆下载栏在屏幕上移动(这是Docker从Docker自己的Docker注册表下载实际的Docker注册表图像)。 如果在一两分钟内一切顺利,你应该看到这样的输出(版本可能会有所不同):

registry_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
registry_1 | time="2015-10-18T23:45:58Z" level=info msg="redis not configured" instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
registry_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
registry_1 | time="2015-10-18T23:45:58Z" level=info msg="listening on [::]:5000" instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
registry_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

不要担心No HTTP secret provided信息。 这是正常的。

大! 此时,您已经有了一个完整的Docker注册表启动和运行,并监听端口5000(这是由设置ports:该位docker-compose.yml文件)。 此时注册表不是有用的 - 它不会启动,除非你手动启动注册表。 此外,Docker注册表没有任何内置的身份验证机制,因此它是不安全的,现在完全向公众开放。

Docker Compose将默认停留等待你输入天长地久,所以,尽管命中CTRL-C关闭您的Docker注册表容器。

第3步 - 设置Nginx容器

让我们开始修复这些安全问题。 第一步是在另一个Docker容器中设置一个Nginx的副本,并将其链接到我们的Docker注册表容器。

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

mkdir ~/docker-registry/nginx

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

nano docker-compose.yml

将以下内容粘贴到文件顶部:

docker-compose.yml
nginx:
  image: "nginx:1.9"
  ports:
    - 5043:443
  links:
    - registry:registry
  volumes:
    - ./nginx/:/etc/nginx/conf.d:ro

这将创建一个基于官方Nginx镜像的新的Docker容器。 这里我们感兴趣的是links部分。 它自动建立一个从一个Docker容器到另一个Docker容器的“链接”。 当Nginx的容器启动时,它就能达到registry的主机名容器registry不管什么实际的IP地址的registry容器结束有。 (幕后Docker实际上是插入进入/etc/hosts在文件nginx容器来告诉它的IP registry容器)。

volumes:节是类似于我们所做的registry容器。 在这种情况下,它给我们一个方法来存储配置文件,我们将使用Nginx在我们的主机,而不是在Docker容器。 :ro在最后只是告诉Docker的Nginx的容器应该只具有只读到主机文件系统的访问。

你的全docker-compose.yml文件现在应该是这样的:

docker-compose.yml
nginx:
  image: "nginx:1.9"
  ports:
    - 5043:443
  links:
    - registry:registry
  volumes:
    - ./nginx/:/etc/nginx/conf.d
registry:
  image: registry:2
  ports:
    - 127.0.0.1:5000:5000
  environment:
    REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
  volumes:
    - ./data:/data

docker-compose up现在开始在同一时间两个容器:一个用于Docker注册表,一个用于Nginx的。

我们需要配置Nginx之前,这将工作,所以让我们创建一个新的Nginx配置文件。

创建registry.conf文件:

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

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

〜/ docker-registry / nginx / registry.conf
upstream docker-registry {
  server registry:5000;
}

server {
  listen 443;
  server_name myregistrydomain.com;

  # SSL
  # ssl on;
  # ssl_certificate /etc/nginx/conf.d/domain.crt;
  # ssl_certificate_key /etc/nginx/conf.d/domain.key;

  # disable any limits to avoid HTTP 413 for large image uploads
  client_max_body_size 0;

  # required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
  chunked_transfer_encoding on;

  location /v2/ {
    # Do not allow connections from docker 1.5 and earlier
    # docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents
    if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
      return 404;
    }

    # To add basic authentication to v2 use auth_basic setting plus add_header
    # auth_basic "registry.localhost";
    # auth_basic_user_file /etc/nginx/conf.d/registry.password;
    # add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;

    proxy_pass                          http://docker-registry;
    proxy_set_header  Host              $http_host;   # required for docker client's sake
    proxy_set_header  X-Real-IP         $remote_addr; # pass on real client's IP
    proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Proto $scheme;
    proxy_read_timeout                  900;
  }
}

保存并退出文件。

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

docker-compose up

Nginx的不打印在启动任何输出,但如果一切顺利的话你现在运行的是设置代理到你的Nginx的一份registry容器。 为了测试它,让我们使用curl ,使一个HTTP请求到我们的Docker直接注册表,然后再拍要求我们的Nginx的端口。 如果一切设置正确的输出会在两种情况下是相同的(因为这写Docker返回一个空的JSON对象“ {}因为Nginx的”)将代理通过对Docker注册表中的请求。

首先,直接向Docker注册表发出一个HTTP请求:

curl http://localhost:5000/v2/

截至本书写Docker返回一个空的json对象,所以你应该看到:

{}

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

curl http://localhost:5043/v2/

您应该看到相同的输出:

{}

如果一切工作正常,你会看到你的一些输出docker-compose终端,它看起来像下面还有:

    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
    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
    registry_1 | 172.17.0.21 - - [11/Aug/2015:10:24:53 +0000] "GET /v2/ HTTP/1.0" 200 2 "" "curl/7.35.0"
    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注册表。

来吧,打CTRL-C在您再次docker-compose终端关闭Docker容器。

第4步 - 设置身份验证

现在Nginx正在代理请求,让我们使用HTTP认证来设置它,以便我们可以控制谁有权访问我们的Docker注册表。 要做到这一点,我们将创建Apache的格式的认证文件通过(Nginx的可以读取它太) htpasswd我们前面安装工具和用户添加到它。

创建第一个用户如下,您要使用的用户名替换用户名

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

系统提示时为此用户创建新密码。

如果你想在将来添加更多的用户,就没有重新运行上面的命令-c选项( c是创建):

htpasswd registry.password USERNAME

在这一点上,我们有一个registry.password与我们的用户文件设置和Docker,注册表提供。 如果您要查看您的用户(如果您要撤消访问权,请删除用户),随时可以查看该文件。

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

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

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

滚动到文件的中间,您将看到一些如下所示的线:

〜/ docker-registry / nginx / registry.conf
# To add basic authentication to v2 use auth_basic setting plus add_header
# auth_basic "registry.localhost";
# auth_basic_user_file /etc/nginx/conf.d/registry.password;
# add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;

取消对与启动两行auth_basic以及与开始的行add_header通过删除#开头的字符
的线。 它应该看起来像这样:

〜/ docker-registry / nginx / registry.conf
# To add basic authentication to v2 use auth_basic setting plus add_header
auth_basic "registry.localhost";
auth_basic_user_file /etc/nginx/conf.d/registry.password;
add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;

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

让我们带回我们的容器,看看身份验证是否正常:

cd ~/docker-registry
docker-compose up

重复上一卷曲测试:

curl http://localhost:5043/v2/

您应该收到一则抱怨未经授权的讯息:

<html>
<head><title>401 Authorization Required</title></head>
<body bgcolor="white">
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx/1.9.7</center>
</body>
</html>

现在尝试添加先前所创建的用户名和密码curl的要求:

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

你应该得到你之前获取相同的输出-空json对象{} 你也应该看到相同的registry_输出docker-compose终端。

继续使用CTRL-Cdocker-compose终端关闭Docker容器。

第5步 - 设置SSL

在这一点上,我们有注册表并运行在Nginx后面,HTTP基本认证工作。 但是,安装仍然不是很安全,因为连接未加密。 您可能已经注意到我们在之前制作的Nginx配置文件中注释掉的SSL行。

让我们启用它们。 首先,打开Nginx配置文件进行编辑:

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

使用箭头键移动并查找这些线:

〜/ docker-registry / nginx / registry.conf
server {
  listen 443;
  server_name myregistrydomain.com;

  # SSL
  # ssl on;
  # ssl_certificate /etc/nginx/conf.d/domain.crt;
  # ssl_certificate_key /etc/nginx/conf.d/domain.key;

通过删除取消对SSL注释下的行#在他们前面的字符。 如果你有一个域名设置为你的服务器的值更改server_name ,而你在它自己的域名。 完成后,文件的顶部应如下所示:

〜/ docker-registry / nginx / registry.conf
server {
  listen 443;
  server_name myregistrydomain.com;

  # SSL
  ssl on;
  ssl_certificate /etc/nginx/conf.d/domain.crt;
  ssl_certificate_key /etc/nginx/conf.d/domain.key;

保存文件。 Nginx的现在配置为使用SSL,并期待为SSL证书和密钥文件的/etc/nginx/conf.d/domain.crt/etc/nginx/conf.d/domain.key分别。 由于映射我们在之前设置docker-compose.yml文件/etc/nginx/conf.d/在Nginx的容器路径对应的文件夹~/docker-registry/nginx/我们的主机上,因此我们将我们的证书文件放在那里。

如果你已经有了一个SSL证书设立或正在计划购买一台,那么你可以只复制证书和密钥文件中列出的路径registry.confssl_certificatessl_certificate_key )。

您还可以得到一个免费的签名SSL证书

否则,我们必须使用自签名的SSL证书。

签署您自己的证书

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

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

cd ~/docker-registry/nginx

生成新的根密钥:

openssl genrsa -out devdockerCA.key 2048

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

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

然后,为您的服务器密钥(这是引用的文件ssl_certificate_key在我们的Nginx的配置):

openssl genrsa -out domain.key 2048

现在我们要做一个证书签名请求。

输入此命令后,OpenSSL将提示您回答几个问题。 写任何你想前几,但是当OpenSSL的提示你输入“通用名”一定要键入您的服务器的域名或IP地址

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

例如,如果你的注册表Docker将要在域中运行www.ilovedocker.com ,那么你的输入应该是这样的:

Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:www.ilovedocker.com
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

不要输入挑战密码。

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

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

由于我们刚刚生成的证书没有通过任何已知的证书颁发机构(例如,VeriSign)进行验证,因此我们需要告诉任何将要使用此Docker注册表的客户端这是合法的证书。 让我们在主机上本地进行,以便我们可以从Docker注册表服务器本身使用Docker:

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

重新启动Docker守护程序,以便它接收对证书存储库的更改:

sudo service docker restart

警告:你必须重复此步骤,为每个连接到该Docker注册表机! 说明如何做到这一点的Ubuntu 14.04的客户都列在第9步-从客户机访问您的Docker登记

第6步 - 测试SSL

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

cd ~/docker-registry
docker-compose up

另做curl从另一个终端测试(仅此一次使用https)来验证我们的SSL设置是否正常工作。 请记住,对于SSL正常工作,你将不得不使用你输入到同一个域名Common Name领域早先的,而你正在创建的SSL证书。

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

注:如果您使用的是自签名的证书,你会看到下面的错误curl

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

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

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

例如,如果用户和密码设置为sammytest ,你的SSL证书是www.example.com ,那么你可以键入以下内容:

curl https://sammy:test@www.example.com:5043/v2/

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

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

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

第7步 - 将SSL端口设置为443

做到这几个步骤就完成了前:更改端口使用标准的SSL端口443 (可选),并设置docker-compose了启动这套在启动容器。

让我们开始设置我们的docker化Nginx容器来监听端口443(SSL的标准端口),而不是我们目前使用的非标准端口5043。 低于1024的端口是在Linux上“特权”端口,虽然,这意味着我们将不得不运行我们的docker-compose容器作为根。

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

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

在Nginx的部分,您会看到一个ports:部分中,更改- 5043:443线(这是我们的主机上映射端口5043到端口443 Nginx的容器内)到- 443:443让我们的Nginx的容器的端口443获得映射到我们的主机的端口443完成后您的docker-compose.yml应该是这样的:

〜/ docker-registry / docker-compose.yml
nginx:
  image: "nginx:1.9"
  ports:
    - 443:443
  links:
    - registry:registry
  volumes:
    - ./nginx/:/etc/nginx/conf.d:ro
registry:
  image: registry:2
  ports:
    - 127.0.0.1:5000:5000
  environment:
    REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
  volumes:
    - ./data:/data

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

sudo docker-compose up

注:只有root用户可以收听你需要使用1024以下的通知港口sudo这次与docker-compose命令,这样可以Nginx的默认SSL端口443上运行。

您应该看到docker-compose启动如常。

让我们尝试另一个curl检测使用的域名,只是这一次,我们不会指定:5043中的网址:

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

如果一切顺利,你应该看到平时registry_在输出docker-compose终端。 您也可以尝试在运行此相同的curl从另一台机器命令以确保您的端口443暴露于外界。

继续使用CTRL-Cdocker-compose终端移动到下一步骤前关闭Docker容器。

第8步 - 启动Docker Registry as a Service

如果一切看上去不错,让我们继续,并创建一个Upstart脚本,使我们的Docker注册表将启动每当系统启动。

首先,我们删除任何现有容器,将我们的Docker注册表移动到系统范围的位置,并将其权限更改为root:

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

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

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

添加以下内容来创建Upstart脚本(获得Upstart妥善监管Docker容器是有点棘手,检查出这篇博客 ,如果你想了解一下这个Upstart脚本所做的更多信息):

/etc/init/docker-registry.conf
description "Docker Registry"

start on runlevel [2345]
stop on runlevel [016]

respawn
respawn limit 10 5

chdir /docker-registry

exec /usr/local/bin/docker-compose up

欲了解更多有关Upstart脚本,请阅读本教程

让我们来测试我们的新的Upstart脚本:

sudo service docker-registry start

你应该看到这样的:

docker-registry start/running, process 25303

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

docker ps

输出应类似于以下(请注意,所有的名字开始dockerregistry_

CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                          NAMES
d4b6fef0b4d1        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
77668352bd39        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 对于我们最后的测试让我们“活钟表”的日志文件tail (的sudo是必要的,因为Upstart日志写入作为root用户):

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

您应该看到平时registry_输出。 从另一个终端或机器继续运行我们现在熟悉的curl测试:

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

如果一切正常卷曲将打印{}到你的终端,你应该看到常用的:

registry_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
registry_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
registry_1 | 172.17.0.4 - - [12/Aug/2015:08:01:12 +0000] "GET /v2/ HTTP/1.0" 200 2 "" "curl/7.37.1"
nginx_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

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

注册服务器 ,查看证书:

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

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

-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJANiXy7fHSPrmMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTQwOTIxMDYwODE2WhcNNDIwMjA2MDYwODE2WjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAuK4kNFaY3k/0RdKRK1XLj9+IrpR7WW5lrNaFB0OIiItHV9FjyuSWK2mj
ObR1IWJNrVSqWvfZ/CLGay6Lp9DJvBbpT68dhuS5xbVw3bs3ghB24TntDYhHMAc8
GWor/ZQTzjccHUd1SJxt5mGXalNHUharkLd8mv4fAb7Mh/7AFP32W4X+scPE2bVH
OJ1qH8ACo7pSVl1Ohcri6sMp01GoELyykpXu5azhuCnfXLRyuOvQb7llV5WyKhq+
SjcE3c2C+hCCC5g6IzRcMEg336Ktn5su+kK6c0hoD0PR/W0PtwgH4XlNdpVFqMST
vthEG+Hv6xVGGH+nTszN7F9ugVMxewIDAQABo1AwTjAdBgNVHQ4EFgQULek+WVyK
dJk3JIHoI4iVi0FPtdwwHwYDVR0jBBgwFoAULek+WVyKdJk3JIHoI4iVi0FPtdww
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkignESZcgr4dBmVZqDwh
YsrKeWSkj+5p9eW5hCHJ5Eg2X8oGTgItuLaLfyFWPS3MYWWMzggxgKMOQM+9o3+k
oH5sUmraNzI3TmAtkqd/8isXzBUV661BbSV0obAgF/ul5v3Tl5uBbCXObC+NUikM
O0C3fDmmeK799AM/hP5CTDehNaFXABGoVRMSlGYe8hZqap/Jm6AaKThV4g6n4F7M
u5wYtI9YDMsxeVW6OP9ZfvpGZW/n/88MSFjMlBjFfFsorfRd6P5WADhdfA6CBECG
LP83r7/MhqO06EOpsv4n2CJ3yoyqIr1L1+6C7Erl2em/jfOb/24y63dj/ATytt2H
6g==
-----END CERTIFICATE-----

将该输出复制到剪贴板,并连接到客户端计算机。

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

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

打开证书文件进行编辑:

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

粘贴证书内容。

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

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

如果一切正常,你会看到同样的文本从早期:

-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJANiXy7fHSPrmMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
...
...
LP83r7/MhqO06EOpsv4n2CJ3yoyqIr1L1+6C7Erl2em/jfOb/24y63dj/ATytt2H
6g==
-----END CERTIFICATE-----

现在更新证书:

sudo update-ca-certificates

你应该得到的输出,看起来像下面这样(注意1 added ):

Updating certificates in /etc/ssl/certs... 1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d....done.

如果您尚未在客户端上安装Docker,请立即执行(请参阅先决条件部分)。

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

sudo service docker restart

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

docker login https://YOUR-DOMAIN

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

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

您应该看到以下消息:

Login Succeeded

在这一点上,你的Docker注册表已经启动并运行了! 让我们做一个测试图像推送到注册表。

第10步 - 发布到您的私人Docker注册表

现在您可以将映像发布到您的私人Docker注册表,但首先我们必须创建一个映像。 我们将创建基于一个简单的图像ubuntu从Docker Hub的形象。

从你的客户机上 ,创建一个小空的形象推向了新的注册表。

docker run -t -i ubuntu /bin/bash

在它完成下载后,你会在一个Docker提示符。 让我们做一个快速变化的文件系统中创建一个名为SUCCESS

touch /SUCCESS

退出Docker容器:

exit

提交更改:

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

此命令创建一个新的形象被称为test-image基于已经在运行的形象,再加上你所做的任何更改的。 在我们的例子中,的加入/SUCCESS文件包含在新的图像。

此图片只在本地存在,所以让我们推送到我们创建的新注册表。

在上一步中,您登录到了您的私有Docker注册表。 如果您还不是登录,让我们再次登录(注意:您要使用https:// ):

docker login https://YOUR-DOMAIN

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

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

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

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

请注意,您先使用图片的本地名称,然后是要添加到其中的标签。 标签使用https:// ,仅仅是域名,端口和图像名称。

现在我们可以把这个图像推送到我们的注册表。 这次我们只使用标记名称:

docker push [YOUR-DOMAIN]/test-image

这将需要一段时间上传到注册表服务器。 您应该看到以类似于以下内容结尾的输出:

latest: digest: sha256:5ea1cfb425544011a3198757f9c6b283fa209a928caabe56063f85f3402363b4 size: 8008

第1步1 - 从你的Docker注册表

为了确保一切正常,让我们回到我们的原始服务器(在那里安装了Docker注册表),并拉我们刚刚从客户端推送的映像。 你也可以从第三个服务器测试这个。

如果Docker未安装在测试服务器上,请返回并按照第6步中的安装说明(如果它是第三个服务器,SSL指示)。

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

docker login https://[YOUR-DOMAIN]

现在拉图像。 You want just the "tag" image name, which includes the domain name, port, and image name (but not https:// ):

docker pull [YOUR-DOMAIN]/test-image

Docker will do some downloading and return you to the prompt. If you run the image on the new machine you'll see that the SUCCESS file we created earlier is there:

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

List your files inside the bash shell:

ls

You should see the SUCCESS file we created earlier for this image:

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

结论

恭喜! You've just used your own private Docker registry to push and pull your first Docker container!

快乐Dockering!