zoukankan      html  css  js  c++  java
  • 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:PASSWORD@localhost: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:PASSWORD@[YOUR-DOMAIN]:5043/v2/

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

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

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

    curl -k https://USERNAME:PASSWORD@[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

  • 相关阅读:
    弦图点染色问题
    BZOJ1098: [POI2007]办公楼biu
    BZOJ1097: [POI2007]旅游景点atr
    BZOJ1068: [SCOI2007]压缩
    BZOJ1055: [HAOI2008]玩具取名
    BZOJ4199: [Noi2015]品酒大会
    BZOJ2527: [Poi2011]Meteors
    BZOJ1493 [NOI2007]项链工厂
    BZOJ1095 ZJOI2007 Hide 捉迷藏
    bzoj1468 Tree
  • 原文地址:https://www.cnblogs.com/sishang/p/6511420.html
Copyright © 2011-2022 走看看