Docker学习笔记六:Docker搭建企业级私有仓库

前言

Docker不仅是一个强大的服务器部署工具,而且它还有一个官方的Docker Hub registry用于储存Docker镜像。上传镜像到Docker Hub是免费的,上传的镜像文件同时也对公共领域开放,而这可能不是我们想要的。

本文介绍如何配置一个私有的Docker registry,在此上传的镜像是私密的,你可以从另一个联网的主机以安全的方式下载此registry上的镜像。

本文仅介绍registry的创建,而不讨论应用的容器化。有关Docker镜像创建的操作可参考这篇Docker入门文章。

本文在Ubuntu 14.04上实测通过,在其他Debian类系统上应该也可以通过。使用的Docker Registry版本为2.0版。
Docker基本概念

如果你此前尚未用过Docker,那么最好先花几分钟时间了解一下它的基本概念。如果你已经使用过Docker,只想了解建立私有registry部分的内容,则可跳过本小节。

Docker入门者可参阅这篇Docker Cheat Sheet。

Docker的核心理念是应用及其依赖项与其运行环境(操作系统)的分离,这种分离通过容器(containers)和镜像(images)来实现。一个Docker镜像本质上来说就是一个文件系统的模板,运行一个Docker镜像就是在你的系统上的一个Docker容器中运行该文件系统的一个实例。默认来说,该容器是不会接触到最初的那个镜像或者Docker运行环境所处的宿主机上的文件系统:该容器是完全独立的环境。

在容器内部操作进行的变更直接在容器中预存,而不会造成初始镜像的变更;要保存这些变更,需要通过docker commit指令将变更提交给指定的Docker镜像。也就是说,从一个旧的容器,你可以不断的生成新的容器,而旧的那个容器(镜像)永远也不会因为意外而被搞砸。该模式对于Git用户而言应该非常眼熟,这相当于创建新的分支(git branch相当于Docker image),运行一个镜像相当于做一次git checkout。

运用同样的类比,一个私有Docker registry就相当于一个私有的git仓库。
准备工作

完成本教程需要如下准备工作:

两台Ubuntu 14.04的云主机,一台作为私有Docker registry服务器,一台作为Docker客户端。
    两台服务器上都建立具有sudo权限的非root用户(用户建立教程可参考这篇文章)。
    两台服务器上都安装Docker以及Docker Compose(安装教程见此)。
    为私有Docker registry服务器配置好可供客户端访问的域名。

步骤1:安全加固

针对Docker Registry的安全加固,建议使用Docker Compose。如此,我们可以在一个容器内运行Docker Registry,而与外部的通讯安全则交给另一个容器内的Nginx来处理。我们在准备工作中应该已经安装过Docker Compose。

用Nginx来处理通讯安全,则需要将可访问私有registry的用户名和密码的列表保存到一个文件里以供Nginx读取。我们将安装apache2-utils软件包,该软件包下的htpasswd可以很方便的生成一个Nginx可读的密码哈希:

sudo apt-get -y install apache2-utils

步骤2:安装配置Docker Registry

如果你只需要管理一两个Docker容器,那么Docker命令行工具就足够好了。然而,大部分在容器内运行的应用并非是独立运作的,他们需要成组配合才能运行。比如,大部分Web应用都至少需要一个Web服务器用于托管应用代码、一个服务器用于运行PHP/Ruby on Rails等解释脚本语言、一台数据库服务器(如MySQL)。

Docker Compose可以让我们为每一个容器用一个.yml配置文件,该文件不仅可以指定容器的配置项,还可以写入有关该容器如何对外通讯的信息。docker-compose命令行工具可以对应用的各个组件下达指令。

Docker registry本身也是一个由多个组件组成的应用,因此我们将使用Docker Compose对其进行配置管理。

最简单的registry配置就是其存储数据的位置。让我们先来创建一个最基本的Docker Compose YAML文件。

首先,创建一个目录,用于储存本教程将要用到的一些文件:

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

在该目录下创建一个docker-compose.yml文件:

nano docker-compose.yml

将如下内容复制粘贴到该文件中:

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

注意这部分内容:environment: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data为Docker registry容器设置了一个环境变量路径/data,如此,Docker registry在启动时就会检查这个环境变量,从而将其数据保存到/data路径下。

最后的volumes: - ./data:/data这一段的意思是,容器内的/data路径应该映射到宿主机的./data路径,也就是说Docker registry的数据都会保存到宿主机的~/docker-registry/data目录下。

现在启动Docker Compose:

cd ~/docker-registry
docker-compose up

输入该命令后,你会看到一系列下载进度条,这些是Docker在从官方Registry下载Docker registry镜像文件的下载进度。如果一切顺利,下载应该在一两分钟内完成,最终呈现的输出应该是这样的:

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 registry已经在运行,监听端口为5000(这个端口可以在docker-compose.yml文件中的ports:部分设置)。不过这个registry现在还用处不大:一方面它需要手动启动,另一方面它还没设置任何身份验证机制所以并不安全。

默认状态下,Docker Compose会一直等待你输入指令。现在我们直接CTRL-C将其关闭退出。
步骤3:设置Nginx容器

现在来解决安全认证的问题。首先我们需要一个Nginx容器,再把它跟刚才的Docker registry容器连接起来。

创建一个新目录用于保存Nginx配置项:

mkdir ~/docker-registry/nginx

打开刚才的docker-compose.yml文件:

nano docker-compose.yml

将下面的内容复制粘贴到文件开头处:

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

这将基于官方Nginx镜像创建一个新的Docker容器。注意这里的links部分,这个功能可以自动建立两个容器之间的连接:当Nginx容器启动时,它将能够直接使用registry这个主机名访问registry容器(无论该容器的IP地址为何。其背后的机制其实是在nginx容器里面的/etc/hosts文件把registry容器的IP自动填写进去)。

volumes:部分跟上面一样,是容器内外路径的映射关系。末尾的:ro意思是只读,即该Nginx容器对宿主机文件系统只有只读权限。

到目前为止,完整的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 registry和一个Nginx。不过我们需要先配置好Nginx。创建一个新的Nginx配置文件registry.conf:

nano ~/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;
  }
}

保存退出。现在可以启动Docker Compose了:

docker-compose up

Nginx在启动时没有输出信息,不过我们可以用curl来测试一下它是不是已经成功启动并连接至registry。首先用curl发送HTTP请求给registry:

curl http://localhost:5000/v2/

你应该能看到返回的结果——一个空json对象:

{}

现在再给Nginx端口发送HTTP请求:

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_这样的前缀(后面的数字不一定是1),则说明一切正常,Nginx已经成功建立了到Docker registry的代理。

CTRL-C退出,准备进行下一步操作。
步骤4:设置验证信息

现在我们需要让Nginx验证访问Docker registry的用户权限。首先我们需要用htpasswd工具创建一个Apache格式的验证文件(Nginx也可以识别该文件):

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

其中的USERNAME是你自己指定的用户名。指令输入后,命令行会请求为该用户建立一个密码。

如果以后要添加新用户,还是一样使用htpasswd工具,只是不用再输入-c选项了(c是新建的意思):

htpasswd registry.password USERNAME

现在我们有了一个registry.password文件,里面保存了可以访问registry的用户名列表。这个文件是可以随时查看编辑的。

接下来需要让Nginx把这个文件用起来。还是打开~/docker-registry/nginx/registry.conf文件:

nano ~/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这两行前面的井号去掉:

# 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;

这样就启动了HTTP验证功能。保存退出,来把容器们启动起来看看:

cd ~/docker-registry
docker-compose up

还是用curl来给Nginx发送请求:

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:[email protected]:5043/v2/

这次,你应该能看到之前的返回结果——空json对象{}。在docker-compose的终端也能够看到registry_部分的内容。

CTRL-C退出,准备进行下一步。
步骤5:设置SSL

虽然已经有了基本的HTTP验证,但现在还是不够安全,因为连接是未加密的。我们需要把SSL启用起来。还是打开刚才的Nginx配置文件:

nano ~/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部分的值改成你的服务器域名:

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将使用/etc/nginx/conf.d/domain.crt证书以及/etc/nginx/conf.d/domain.key密钥来提供SSL服务。根据之前的配置,容器内的/etc/nginx/conf.d/路径是映射到宿主机的~/docker-registry/nginx/路径下,所以我们需要把证书文件复制到这里。你可以购买证书,也可以获取一个免费的SSL证书。或者,你也可以使用自签名的SSL证书。
自签名的SSL证书

目前为止,Docker还无法正式支持自签名的SSL证书,所以这个配置起来要麻烦一些——我们需要将宿主机设置为证书的颁发机构。

到~/docker-registry/nginx目录下,创建一个新的root key:

cd ~/docker-registry/nginx
openssl genrsa -out devdockerCA.key 2048

生成一个root证书(需要填写国家省市信息之类的,这些可以随便填):

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

然后,生成key(这个密钥就是上面需要用到的ssl_certificate_key):

openssl genrsa -out domain.key 2048

然后,我们需要进行一个证书签名的请求。

输入如下命令。输入之后,OpenSSL会向你提出几个问题。其他问题怎么回答都好,不过关于"Common Name"这一项,务必要填写服务器的域名或IP:

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

比如,如果你的Docker registry使用的域名是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 []:

A challenge password []:这里不要填。

然后,我们要给这个证书请求做签名:

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

因为我们刚才生成的这些证书没有被任何权威机构(比如VeriSign)验证过,因此我们需要用另外的方法告诉所有使用这个Docker registry的客户端说,这个Docker registry使用的证书是合法的。这个方法就是,在每个Docker客户端上做如下设置(需要把刚才生成的devdockerCA.crt复制过去):

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

详细配置过程见本文步骤9。上述指令在本机执行可直接生效。
步骤6:测试SSL

现在启动容器:

cd ~/docker-registry
docker-compose up

再做一次curl,但是用https(这里输入的域名或IP必须与刚才在证书生成过程中填写的Common Name部分完全一致):

curl https://USERNAME:[email protected][YOUR-DOMAIN]:5043/v2/

如果刚才用了自签名证书,你会看到如下问题报告:

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

为curl命令加上-k选项可以跳过该验证:

curl -k https://USERNAME:[email protected][YOUR-DOMAIN]:5043/v2/

如此,应该可以得到空json对象{}的返回结果。docker-compose的终端窗口那边也会输出registry_部分内容。否则的话,则需要回去重新检查SSL设置的步骤。

至此,如果你的防火墙配置允许来自外部的请求访问5043端口,则你应该可以使用自己的用户名和密码通过docker login https://<YOURDOMAIN>登陆到该Docker registry上了。
步骤7:将SSL端口设置为443

443是标准的SSL端口,所以我们要把之前设置的5043改成443。不过在Linux上,1024以下的端口都是“特权”端口,所以docker-compose容器必须以root权限运行才能使用该端口。

打开docker-compose.yml进行编辑:

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

在Nginx部分的ports:段落,原本的内容是- 5043:443,即把宿主机的5043端口映射到Nginx容器的443端口。我们要把它改成- 443:443:

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

CTRL-C退出之前运行的docker-compose(如果之前已经退出就无需进行此操作),然后以sudo权限再次启动:

sudo docker-compose up

现在docker-compose已经启动,再次使用curl命令来做一次测试。这次我们在URL中不再指定端口:

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

检查返回的结果是否为{},docker-compose终端窗口的输出是否包含registry_。在外部的另一台机器上重复本操作,以确保Docker registry可以从外部访问。

如果一切正常,CTRL-C退出,准备进行下一步。
步骤8:将Docker Registry启动为服务

接下来我们创建一个Upstart脚本以使Docker registry在每次系统启动时一起启动。

首先我们需要移除之前已经生成的容器,好把整个Docker registry目录移动到系统通用目录下,再将其权限更改为root权限:

cd ~/docker-registry
docker-compose rm   # 移除现有的容器
sudo mv ~/docker-registry /docker-registry
sudo chown -R root: /docker-registry

然后创建一个Upstart脚本:

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

将以下内容复制粘贴到文件中(该脚本内容有一些复杂,其说明可参考这篇博文。有关Upstart的用法可参考这篇教程。):

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脚本:

sudo service docker-registry start

返回的结果应该是这样的:

docker-registry start/running, process 25303

使用如下命令检查Docker服务是否已经在运行:

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到registry服务器上:

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 Registry的客户端

如步骤5所述,对于使用自签名SSL证书的情况,所有需要访问该Docker registry的客户端都需要添加我们创建的证书。我们需要把~/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

再创建证书文件,使用同样的文件名devdockerCA.crt:

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

将刚才复制到剪贴板上的内容粘贴进来。保存退出。再使用cat查看一下新创建的文件,检查内容是否正确:

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

确认无误后,更新证书信息:

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以重新加载系统CA证书列表:

sudo service docker restart

现在可以使用如下指令登入Docker registry了:

docker login https://YOUR-DOMAIN

服务器会要求你输入用户名、密码和Email。用户名和密码就是刚才在服务器上创建的,Email可以随便填:

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

步骤10:将本机镜像发布到Docker Registry

我们先在客户端上创建一个简单的镜像(基于Docker Hub上的ubuntu镜像。如果本机上已经有镜像那就可以省去这一步了):

docker run -t -i ubuntu /bin/bash

该指令会下载ubuntu镜像并运行其中的bash以等待我们给该容器输入指令,这可能需要一段时间。等等待输入的指令出现之后,我们来创建一个文件SUCCESS:

touch /SUCCESS

现在可以退出容器了:

exit

将变更后的镜像提交为test-image:

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

根据我们上面的操作,这个test-image镜像与官方ubuntu镜像相比,只是添加了一个空文件SUCCESS。

现在我们把这个测试镜像推送到registry。

登陆到registry服务器:

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的设计,我们推送之前,需要给它加一个tag用于标注registry的位置:

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

这里需要注意的是,tag中的域名不需要https://,只需要域名、端口、加上镜像名称即可。

现在可以推送了:

docker push [YOUR-DOMAIN]/test-image

推送需要一段时间,完成后应该能看到如下内容:

latest: digest: sha256:5ea1cfb425544011a3198757f9c6b283fa209a928caabe56063f85f3402363b4 size: 8008

步骤11:从Docker Registry拉取镜像

现在测试从另一台机器拉取该镜像(我们也可以直接在registry服务器上进行本测试)。

登陆到registry服务器:

docker login https://[YOUR-DOMAIN]

使用刚才创建的tag拉取镜像:

docker pull [YOUR-DOMAIN]/test-image

Docker会下载该镜像。下载完成后,输入如下指令运行镜像以进入到里面:

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

看看里面是不是有刚才创建的文件:

ls

应该可以看到SUCCESS文件出现在列表中:

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

总结

至此,我们已经成功创建了一个私有Docker Registry服务器,并且完成了镜像的推送和拉取。现在可以尽情的玩弄你的Docker啦!

转载:http://blog.csdn.net/zstack_org/article/details/53301211?locationNum=12&fps=1

时间: 2024-11-04 18:56:35

Docker学习笔记六:Docker搭建企业级私有仓库的相关文章

Docker学习笔记 之 Docker安装配置使用

简介 Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的.可移植的.自给自足的容器.开发者在笔记本上编译测试通过的容器可以批量地在生产环境中部署,包括VMs(虚拟机).bare metal.OpenStack 集群和其他的基础应用平台. 环境:CentOS7.3 地址:192.168.1.137 首先注册阿里云开发者帐号帐号 https://cr.console.aliyun.com/ 登陆后取得专属加速器地址:https://XXXXX.mirror.aliyuncs.com

[转]Docker学习笔记之一,搭建一个JAVA Tomcat运行环境

本文转自:http://www.blogjava.net/yongboy/archive/2013/12/12/407498.html 前言 Docker旨在提供一种应用程序的自动化部署解决方案,在 Linux 系统上迅速创建一个容器(轻量级虚拟机)并部署和运行应用程序,并通过配置文件可以轻松实现应用程序的自动化安装.部署和升级,非常方便.因为使用了容器,所以可以很方便的把生产环境和开发环境分开,互不影响,这是 docker 最普遍的一个玩法.更多的玩法还有大规模 web 应用.数据库部署.持续

docker学习笔记(二)——创建私有库

本篇将介绍在docker在linux上创建私有库. 目录: 1.介绍 2.创建docker私有库 3.测试 4.参考资料 1.介绍 docker默认使用docker提供的公共库,在某些场合下,需要建立私有仓库来管理镜像.这里我们使用Docker Registry v2.0来管理docker镜像仓库. github地址:https://github.com/docker/distribution 2.创建docker私有库 启动Registry: $ docker run -d -p 5000:5

Docker学习笔记之一,搭建一个JAVA Tomcat运行环境

前言 Docker旨在提供一种应用程序的自动化部署解决方案,在 Linux 系统上迅速创建一个容器(轻量级虚拟机)并部署和运行应用程序,并通过配置文件可以轻松实现应用程序的自动化安装.部署和升级,非常方便.因为使用了容器,所以可以很方便的把生产环境和开发环境分开,互不影响,这是 docker 最普遍的一个玩法.更多的玩法还有大规模 web 应用.数据库部署.持续部署.集群.测试环境.面向服务的云计算.虚拟桌面 VDI 等等. 主观的印象:Docker 使用 Go 语言编写,用 cgroup 实现

docker 学习笔记之docker连接网络的设置

1.如果docker主机不需要通过代理连接外网 则docker的相关命令(如docker search)或docker容器与网络相关的操作都可以正常进行,不需要特殊设置. 2.当docker主机 是通过代理才能连接外网时,采用服务方式启动守护进程 如果docker守护进程是通过服务的方式启动的(sudo start docker) 当我们执行如  docker search ubuntu 命令时,会报错 Error response from daemon: Get https://index.

Docker学习笔记(3) — docker仓库的镜像怎么删除

docker越来越炙手可热,如果你的团队已经准备开始使用docker,那么私有仓库是必不可少的东西,首先是可以帮助你加快从服务器pull镜像的速度,其次也可以帮助你存放私有的镜像,本文主要为大家介绍如何从公用服务器上讲开放的images备份到本地私有服务器上.docker images往往不知不觉就占满了硬盘空间,为了清理冗余的image,可采用以下方法: 1.进入root权限 sudo su 2.停止所有的container,这样才能够删除其中的images: docker stop $(do

Docker学习笔记(2)--Docker常用命令

原文地址:http://blog.csdn.net/we_shell/article/details/38368137 1. 查看docker信息(version.info) [plain] view plaincopy # 查看docker版本 $docker version # 显示docker系统的信息 $docker info 2. 对image的操作(search.pull.images.rmi.history) [plain] view plaincopy # 检索image $do

Docker学习笔记(2)-docker镜像操作

本节将会涉及Docker的镜像操作. 1. 获取镜像 如何获取Docker Hub上的镜像?可通过docker pull命令获取,其格式为: docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签],具体可通过docker pull --help命令查看. Docker镜像仓库地址的格式一般为<域名/IP>[:端口号],仓库名一般为两段式名称,即<用户名>/<软件名>,对于Docker Hub,默认的用户名为library

Docker学习笔记之docker数据卷

Docker数据卷数据卷是经过特殊设计的目录,可用绕过联合文件系统(UFS),为一个或多个容器提供访问 数据卷的特点:数据卷在容器启动时初始化,如果容器使用的镜像在挂载点包含了数据,这些数据会拷贝到新初始化的数据卷中数据卷可以在容器之间共享和重用可以对数据卷里的内容直接进行修改数据卷的变化不会影响镜像的更新卷会一直存在,即使挂载数据卷的容器已经被删除 为容器添加数据卷:docker run -v ~/container_data:/data -it centos /bin/bash:contai