docker CE on Linux示例浅析(六)注册与镜像仓库

概述

github项目地址:https://github.com/superwujc

尊重原创,欢迎转载,注明出处:https://my.oschina.net/superwjc/blog/3061394

历史系列:

docker CE on Linux示例浅析(一)安装与基本运行

docker CE on Linux示例浅析(二)数据存储与持久化

docker CE on Linux示例浅析(三)镜像与容器管理

docker CE on Linux示例浅析(四)swam群集配置

docker CE on Linux示例浅析(五)服务编排

    镜像仓库(repository)是一系列镜像组成的集合,单一仓库内包含若干名称相同的镜像,以标签(tag)进行区分。因此,镜像名用于引用仓库,而标签用于引用镜像。所有与镜像相关的操作中,指定镜像实际为指定仓库名与镜像标签,二者之间以冒号分隔,形式为仓库名:标签。标签可以为镜像的构建日期,或容器内运行代码的版本号,若未显式指定,则默认为latest。例如,对于镜像mysql:5.6.44,mysql:5.7.26与mysql:8.0.16,三者同属于mysql仓库,以版本号作为标签。

    注册(registry)是提供镜像仓库功能的服务端程序,单一注册运行后包含若干镜像仓库,例如centos,mysql,nginx等。注册以IP地址/域名[:端口]进行引用,截至18.09.6版本,docker-ce以硬编码的方式将registry-1.docker.io作为默认的注册地址(可以通过源码,或在拉取镜像的同时运行tcpdump等抓包工具查看)。

    本地docker-ce引擎所使用的注册是守护进程配置的一部分,可通过以下3种方式之一进行设置:

  • dockerd命令的--registry-mirror选项。
  • 守护进程配置文件(默认为/etc/docker/daemon.json)的registry-mirrors字段。
  • 操作系统特定的守护进程管理工具,如CentOS的systemd。

    简而言之,镜像仓库是注册的运行实例。注册以IP地址或域名进行引用,内包含若干镜像仓库;镜像仓库以镜像名称进行引用,内包含若干镜像;镜像以标签进行引用,用于指定所有与镜像相关操作的对象。指定一个镜像时,完整的形式为注册地址/仓库名称:镜像标签,若未显式指定注册地址,则为--registry-mirror命令行选项或registry-mirrors配置文件字段指定的地址,默认为registry-1.docker.io。镜像仓库通常也用于指代注册。

    镜像仓库分为公有(public)与私有(private),公有仓库(如docker hub与阿里云镜像仓库)提供了基础功能镜像的免费获取,私有仓库则用于生产环境中数据安全性与可控性的场景。本文将简述私有镜像仓库的部署与相关应用。

示例

环境

  • 宿主机2台:dock_host_0(192.168.9.168/24),dock_host_1(192.168.9.169/24),系统与软件环境一致,均为全新最小化安装,单物理网卡,操作系统版本CentOS Linux release 7.6.1810 (Core),内核版本3.10.0-957.21.2.el7.x86_64,关闭selinux与防火墙。
  • docker为默认安装,版本18.09.6,无其他额外设置。
[root@docker_host_0 ~]# ip addr show eth0 | sed -n '/inet /p' | awk '{print $2}'
192.168.9.168/24
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# uname -r
3.10.0-957.21.2.el7.x86_64
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker -v
Docker version 18.09.6, build 481bc77156
[root@docker_host_0 ~]#
[root@docker_host_1 ~]# ip addr show eth0 | sed -n '/inet /p' | awk '{print $2}'
192.168.9.169/24
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# uname -r
3.10.0-957.21.2.el7.x86_64
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# docker -v
Docker version 18.09.6, build 481bc77156
[root@docker_host_1 ~]#

获取镜像

以registry-1.docker.io/library/以及默认的注册地址拉取registry镜像,执行成功后,本地包含该镜像的两个实例,除REPOSITORY不同外,TAG,DIGEST,IMAGE ID均相同,表明二者引用同一镜像。

[root@docker_host_0 ~]# docker image ls -a
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker pull registry-1.docker.io/library/registry
Using default tag: latest
latest: Pulling from library/registry
c87736221ed0: Pull complete
1cc8e0bb44df: Pull complete
54d33bcb37f5: Pull complete
e8afc091c171: Pull complete
b4541f6d3db6: Pull complete
Digest: sha256:f87f2b82b4873e0651f928dcde9556008314543bd863b3f7e5e8d03b04e117f7
Status: Downloaded newer image for registry-1.docker.io/library/registry:latest
[root@docker_host_0 ~]#
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker pull registry
Using default tag: latest
latest: Pulling from library/registry
Digest: sha256:f87f2b82b4873e0651f928dcde9556008314543bd863b3f7e5e8d03b04e117f7
Status: Downloaded newer image for registry:latest
[root@docker_host_0 ~]#
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker image ls -a --digests
REPOSITORY                              TAG                 DIGEST                                                                    IMAGE ID            CREATED             SIZE
registry-1.docker.io/library/registry   latest              sha256:f87f2b82b4873e0651f928dcde9556008314543bd863b3f7e5e8d03b04e117f7   f32a97de94e1        3 months ago        25.8MB
registry                                latest              sha256:f87f2b82b4873e0651f928dcde9556008314543bd863b3f7e5e8d03b04e117f7   f32a97de94e1        3 months ago        25.8MB
[root@docker_host_0 ~]#

    查看注册镜像版本:

[root@docker_host_0 ~]# docker run -it --rm registry:latest registry -v
registry github.com/docker/distribution v2.7.1
[root@docker_host_0 ~]#

配置方式

    注册镜像以alpine linux为基础镜像(base image)进行构建。2.7.1版本在amd64架构下的Dockerfile文件内容为:

# Build a minimal distribution container

FROM alpine:3.8

RUN set -ex \
    && apk add --no-cache ca-certificates apache2-utils

COPY ./registry /bin/registry
COPY ./config-example.yml /etc/docker/registry/config.yml

VOLUME ["/var/lib/registry"]
EXPOSE 5000

COPY docker-entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

CMD ["/etc/docker/registry/config.yml"]

    Dockerfile主要执行以下初始化操作:

  • 将/bin/registry作为主要命令,用于实现注册镜像的功能。
  • 将/entrypoint.sh脚本作为镜像启动时的默认入口点(ENTRYPOINT指令),可以在创建容器或服务时以--entrypoint选项显式指定。
  • 将/etc/docker/registry/config.yml配置文件作为默认入口点命令/参数(CMD指令),可以在创建容器或服务时显式指定。
  • 创建匿名数据卷(VOLUME指令),目标挂载路径为容器的/var/lib/registry目录,可以在创建容器或服务时以--mount/-v选项显式指定挂载源路径。
  • 对外开放5000端口(EXPOSE指令),可以通过配置文件或环境变量显式指定。

    入口点entrypoint.sh脚本的内容为:

#!/bin/sh

set -e

case "$1" in
    *.yaml|*.yml) set -- registry serve "$@" ;;
    serve|garbage-collect|help|-*) set -- registry "$@" ;;
esac

exec "$@"

    entrypoint.sh脚本根据命令行参数执行以下操作:

  • 若第一个参数($1)为YAML格式的文件(后缀为.yaml或.yml),则以该文件作为参数,执行registry serve命令;或
  • 若第一个参数为serve/garbage-collect/help,则以该参数作为registry命令的参数,并执行相应的操作;或
  • 根据命令行参数执行相应的操作。

    /etc/docker/registry/config.yml文件的初始内容为:

version: 0.1
log:
  fields:
    service: registry
storage:
  cache:
    blobdescriptor: inmemory
  filesystem:
    rootdirectory: /var/lib/registry
http:
  addr: :5000
  headers:
    X-Content-Type-Options: [nosniff]
health:
  storagedriver:
    enabled: true
    interval: 10s
    threshold: 3

    注册镜像启动与运行时的行为可以通过YAML配置文件环境变量进行指定,二者之间具有一一对应的关系。环境变量根据配置文件中的选项与缩进等级进行命名,以REGISTRY作为起始部分,形式为REGISTRY_variable(下划线(_)表示缩进等级,variable为配置选项的大写形式)。例如,以下配置文件段落用于指定后端存储,对应的环境变量名称为REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY:

storage:
  filesystem:
    rootdirectory: /var/lib/registry

    docker官方文档中包含所有注册镜像支持的配置选项列表,常用的环境变量包括:

  • REGISTRY_HTTP_ADDR:注册镜像运行时监听的IP地址与端口(默认为0.0.0.0:5000)。
  • REGISTRY_HTTP_TLS_CERTIFICATE:ssl签名证书的位置。
  • REGISTRY_HTTP_TLS_KEY:SSL私钥的位置。
  • REGISTRY_AUTH:认证方式。
  • REGISTRY_AUTH_HTPASSWD_REALM:Apache htpasswd认证区域(功能类似于nginx的auth_basic指令)。
  • REGISTRY_AUTH_HTPASSWD_PATH:Apache htpasswd认证文件的位置(功能类似于nginx的auth_basic_user_file指令)。注册容器自身强制使用bcrypt加密算法(htpasswd命令的-B选项),使用其他加密算法都将被忽略,且导致注册镜像启动失败。使用前端代理服务器(如nginx与apache httpd)时,需要确认代理实现是否支持相应的加密算法。

基本功能

    运行注册镜像,名称为test-repos,监听地址为0.0.0.0:5200:

[root@docker_host_0 ~]# docker run -dit --name test-repos --restart always -e REGISTRY_HTTP_ADDR=0.0.0.0:5200 -p 5200:5200 registry:latest
be53ddc214973292c4be0f535225f65a1ebe3b69f06e67b75afd766311284c04
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker container ls -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                              NAMES
be53ddc21497        registry:latest     "/entrypoint.sh /etc…"   8 seconds ago       Up 7 seconds        5000/tcp, 0.0.0.0:5200->5200/tcp   test-repos
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# ss -atn | grep 5200
LISTEN     0      128         :::5200                    :::*
[root@docker_host_0 ~]#

    在镜像标签(tag)中将注册地址设置为127.0.0.1:5200,并推送至本地仓库:

[root@docker_host_0 ~]# docker pull centos
Using default tag: latest
latest: Pulling from library/centos
8ba884070f61: Pull complete
Digest: sha256:b5e66c4651870a1ad435cd75922fe2cb943c9e973a9673822d1414824a1d0475
Status: Downloaded newer image for centos:latest
[root@docker_host_0 ~]#
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker image tag centos:latest 127.0.0.1:5200/centos:new
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker push 127.0.0.1:5200/centos:new
The push refers to repository [127.0.0.1:5200/centos]
d69483a6face: Pushed
new: digest: sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66 size: 529
[root@docker_host_0 ~]#

    拉取本地仓库镜像:

[root@docker_host_0 ~]# docker image rm 127.0.0.1:5200/centos:new
Untagged: 127.0.0.1:5200/centos:new
Untagged: 127.0.0.1:5200/centos@sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66
[root@docker_host_0 ~]#
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker image ls -a
REPOSITORY                              TAG                 IMAGE ID            CREATED             SIZE
centos                                  latest              9f38484d220f        3 months ago        202MB
registry                                latest              f32a97de94e1        3 months ago        25.8MB
registry-1.docker.io/library/registry   latest              f32a97de94e1        3 months ago        25.8MB
[root@docker_host_0 ~]#
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker pull 127.0.0.1:5200/centos:new
new: Pulling from centos
Digest: sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66
Status: Downloaded newer image for 127.0.0.1:5200/centos:new
[root@docker_host_0 ~]#
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker image ls -a
REPOSITORY                              TAG                 IMAGE ID            CREATED             SIZE
127.0.0.1:5200/centos                   new                 9f38484d220f        3 months ago        202MB
centos                                  latest              9f38484d220f        3 months ago        202MB
registry                                latest              f32a97de94e1        3 months ago        25.8MB
registry-1.docker.io/library/registry   latest              f32a97de94e1        3 months ago        25.8MB
[root@docker_host_0 ~]#

    registry镜像启动时,默认将自动创建匿名数据卷,用于存储镜像,并以只读方式挂载至容器的/var/lib/registry目录;可以显式指定挂载选项(--mount),将镜像存储的位置设置为宿主机上的命名数据卷或源路径。

[root@docker_host_0 ~]# docker container inspect test-repos | less
...
        "Mounts": [
            {
                "Type": "volume",
                "Name": "d2119dd7693f6bcc750fa2f3b266ef29ac780e8f9c2623c3876584f1c82c1bb8",
                "Source": "/var/lib/docker/volumes/d2119dd7693f6bcc750fa2f3b266ef29ac780e8f9c2623c3876584f1c82c1bb8/_data",
                "Destination": "/var/lib/registry",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
...
[root@docker_host_0 ~]# 
[root@docker_host_0 ~]# docker volume ls
DRIVER              VOLUME NAME
local               d2119dd7693f6bcc750fa2f3b266ef29ac780e8f9c2623c3876584f1c82c1bb8
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# ll /var/lib/docker/volumes/d2119dd7693f6bcc750fa2f3b266ef29ac780e8f9c2623c3876584f1c82c1bb8/_data/
total 0
drwxr-xr-x 3 root root 22 Jun 12 22:30 docker
[root@docker_host_0 ~]#

    注册支持一系列HTTP API,其中,GET /v2/_catalogGET /v2/镜像或仓库名称/tags/list分别用于获取指定注册中包含的所有仓库,以及仓库中包含的所有镜像。

[root@docker_host_0 ~]# curl -X GET 127.0.0.1:5200/v2/_catalog -i
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Docker-Distribution-Api-Version: registry/2.0
X-Content-Type-Options: nosniff
Date: Wed, 12 Jun 2019 22:39:33 GMT
Content-Length: 28

{"repositories":["centos"]}
[root@docker_host_0 ~]#
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# curl -X GET 127.0.0.1:5200/v2/centos/tags/list -i
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Docker-Distribution-Api-Version: registry/2.0
X-Content-Type-Options: nosniff
Date: Wed, 12 Jun 2019 22:39:46 GMT
Content-Length: 33

{"name":"centos","tags":["new"]}
[root@docker_host_0 ~]#

网络访问

    注册容器默认仅可对本机(localhost/127.0.0.1)提供http方式的镜像传输,其他网络客户端尝试拉取或推送镜像将提示"server gave HTTP response to HTTPS client"错误。

[root@docker_host_0 ~]# docker image tag centos:latest 192.168.9.168:5200/centos:new
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker push 192.168.9.168:5200/centos:new
The push refers to repository [192.168.9.168:5200/centos]
Get https://192.168.9.168:5200/v2/: http: server gave HTTP response to HTTPS client
[root@docker_host_0 ~]#
[root@docker_host_1 ~]# docker pull 192.168.9.168:5200/centos:new
Error response from daemon: Get https://192.168.9.168:5200/v2/: http: server gave HTTP response to HTTPS client
[root@docker_host_1 ~]#

    网络访问功能可以通过以下2种方式之一进行设置:

  • http方式:客户端通过dockerd命令的--insecure-registry选项,或配置文件的insecure-registries字段,指定注册的IP地址/域名与端口;服务端无需额外配置(非强制使用https方式)。出于安全性考虑,生产环境中不推荐使用该方式。
  • https方式:服务端配置TLS证书加密,客户端配置相应的证书信任。

http方式

    指定配置文件的insecure-registries字段,并重启docker守护进程:

[root@docker_host_0 ~]# vi /etc/docker/daemon.json
{
    "insecure-registries": ["192.168.9.168:5200"]
}
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# systemctl restart docker
[root@docker_host_0 ~]#
[root@docker_host_1 ~]# vi /etc/docker/daemon.json
{
    "insecure-registries": ["192.168.9.168:5200"]
}
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# systemctl restart docker
[root@docker_host_1 ~]#

    设置注册地址,拉取与推送镜像:

[root@docker_host_0 ~]# docker push 192.168.9.168:5200/centos:new
The push refers to repository [192.168.9.168:5200/centos]
d69483a6face: Layer already exists
new: digest: sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66 size: 529
[root@docker_host_0 ~]#
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker image rm 192.168.9.168:5200/centos:new
Untagged: 192.168.9.168:5200/centos:new
Untagged: 192.168.9.168:5200/centos@sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66
[root@docker_host_0 ~]#
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker pull 192.168.9.168:5200/centos:new
new: Pulling from centos
Digest: sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66
Status: Downloaded newer image for 192.168.9.168:5200/centos:new
[root@docker_host_0 ~]#
[root@docker_host_1 ~]# docker pull 192.168.9.168:5200/centos:new
new: Pulling from centos
8ba884070f61: Pull complete
Digest: sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66
Status: Downloaded newer image for 192.168.9.168:5200/centos:new
[root@docker_host_1 ~]#

https方式

    本节以repos.abc.com域名的自签名证书(self-signed)为例。

服务端

    将docker_host_0作为服务端,以本地hosts的方式设置域名解析:

[root@docker_host_0 ~]# echo -e '127.0.0.1\trepos.abc.com' >> /etc/hosts
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# ping -c 3 repos.abc.com
PING repos.abc.com (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.226 ms
64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.041 ms
64 bytes from localhost (127.0.0.1): icmp_seq=3 ttl=64 time=0.056 ms

--- repos.abc.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 0.041/0.107/0.226/0.084 ms
[root@docker_host_0 ~]#

    生成签名证书(.crt)与私钥(.key)文件:

通过openssl创建证书的过程中,需要根据提示输入一系列信息,其中,通用名(Common Name)为证书对应的域名或IP地址,该字段为必选,其他字段均为可选。

[root@docker_host_0 ~]# mkdir -p /opt/certs
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# openssl req -new -newkey rsa:4096 -x509 -sha256 -days 365 -nodes -out /opt/certs/repos.abc.com.crt -keyout /opt/certs/repos.abc.com.key
Generating a 4096 bit RSA private key
..........................................................++
.........++
writing new private key to '/opt/certs/repos.abc.com.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:repos.abc.com
Email Address []:
[root@docker_host_0 ~]#
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# ll /opt/certs/
total 8
-rw-r--r-- 1 root root 1976 Jun 12 22:55 repos.abc.com.crt
-rw-r--r-- 1 root root 3272 Jun 12 22:55 repos.abc.com.key
[root@docker_host_0 ~]#

    运行注册镜像,名称为net-repos:

[root@docker_host_0 ~]# docker container rm -f test-repos
test-repos
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker container ls -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker run -d \
> --name net-repos \
> --restart always \
> --mount type=bind,src=/opt/certs,dst=/certs,ro \
> -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
> -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/repos.abc.com.crt \
> -e REGISTRY_HTTP_TLS_KEY=/certs/repos.abc.com.key \
> -p 443:443 \
> registry:latest
019278d214eeada96a0382bff049b490314a50bcc543d0a9c47f1605921b4309
[root@docker_host_0 ~]#
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker container ls -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                            NAMES
019278d214ee        registry:latest     "/entrypoint.sh /etc…"   11 seconds ago      Up 10 seconds       0.0.0.0:443->443/tcp, 5000/tcp   net-repos
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# ss -atn | grep 443
LISTEN     0      128         :::443                     :::*
[root@docker_host_0 ~]#

    设置镜像标签(tag)并执行推送:

[root@docker_host_0 ~]# docker image tag centos:latest repos.abc.com/centos:net
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker push repos.abc.com/centos:net
The push refers to repository [repos.abc.com/centos]
d69483a6face: Pushed
net: digest: sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66 size: 529
[root@docker_host_0 ~]#

    查看所有仓库与对应的标签(tag):

curl命令的--cacert选项用于指定证书(.crt/.pem)文件。

[root@docker_host_0 ~]# curl --cacert /opt/certs/repos.abc.com.crt -X GET https://repos.abc.com/v2/_catalog -i
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Docker-Distribution-Api-Version: registry/2.0
X-Content-Type-Options: nosniff
Date: Wed, 12 Jun 2019 23:04:47 GMT
Content-Length: 28

{"repositories":["centos"]}
[root@docker_host_0 ~]#
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# curl --cacert /opt/certs/repos.abc.com.crt -X GET https://repos.abc.com/v2/centos/tags/list -i
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Docker-Distribution-Api-Version: registry/2.0
X-Content-Type-Options: nosniff
Date: Wed, 12 Jun 2019 23:05:26 GMT
Content-Length: 33

{"name":"centos","tags":["net"]}
[root@docker_host_0 ~]#

    拉取镜像:

[root@docker_host_0 ~]# docker image rm repos.abc.com/centos:net
Untagged: repos.abc.com/centos:net
Untagged: repos.abc.com/centos@sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker pull repos.abc.com/centos:net
net: Pulling from centos
Digest: sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66
Status: Downloaded newer image for repos.abc.com/centos:net
[root@docker_host_0 ~]#
客户端

    将docker_host_1作为客户端,以本地hosts的方式设置域名解析:

[root@docker_host_1 ~]# echo -e '192.168.9.168\trepos.abc.com' >> /etc/hosts
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# ping -c 3 repos.abc.com
PING repos.abc.com (192.168.9.168) 56(84) bytes of data.
64 bytes from repos.abc.com (192.168.9.168): icmp_seq=1 ttl=64 time=0.726 ms
64 bytes from repos.abc.com (192.168.9.168): icmp_seq=2 ttl=64 time=0.704 ms
64 bytes from repos.abc.com (192.168.9.168): icmp_seq=3 ttl=64 time=0.615 ms

--- repos.abc.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 0.615/0.681/0.726/0.056 ms
[root@docker_host_1 ~]#

    设置服务端证书信任,Linux客户端需要将服务端的签名证书(.crt)复制为本端的/etc/docker/certs.d/IP地址或域名[:端口]/ca.crt文件,否则获取镜像时将导致x509错误(将服务端自身无需执行该设置)。

[root@docker_host_1 ~]# docker pull repos.abc.com/centos:net
Error response from daemon: Get https://repos.abc.com/v2/: x509: certificate signed by unknown authority
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# mkdir -p /etc/docker/certs.d/repos.abc.com/
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# scp root@192.168.9.168:/opt/certs/repos.abc.com.crt /etc/docker/certs.d/repos.abc.com/ca.crt
repos.abc.com.crt                                              100% 1976     1.5MB/s   00:00
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# docker pull repos.abc.com/centos:net
net: Pulling from centos
Digest: sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66
Status: Downloaded newer image for repos.abc.com/centos:net
[root@docker_host_1 ~]#

登录认证

    htpasswd是注册镜像提供的原生认证方式,本节以此为例。

    注册镜像强制使用密文传输认证用户与密码,因此登录认证首先须在服务端配置TLS证书加密。

    服务端生成htpasswd密码文件/opt/auth/registry.htpasswd,用户名为testuser,密码为testpassword,加密方式为bcrypt:

[root@docker_host_0 ~]# mkdir -p /opt/auth
[root@docker_host_0 ~]# 
[root@docker_host_0 ~]# docker run --rm --entrypoint htpasswd registry:latest -Bbn testuser testpassword > /opt/auth/registry.htpasswd
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# ll /opt/auth/registry.htpasswd
-rw-r--r-- 1 root root 71 Jun 12 23:58 /opt/auth/registry.htpasswd
[root@docker_host_0 ~]#

    服务端运行注册镜像,名称为auth-repos:

[root@docker_host_0 ~]# docker container rm -f net-repos
net-repos
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker container ls -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@docker_host_0 ~]#
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker run -d \
> --name auth-repos \
> --restart always \
> --mount type=bind,src=/opt/certs,dst=/certs,ro \
> --mount type=bind,src=/opt/auth,dst=/auth,ro \
> -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
> -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/repos.abc.com.crt \
> -e REGISTRY_HTTP_TLS_KEY=/certs/repos.abc.com.key \
> -p 443:443 \
> registry:latest
4b6078987966ab361af4edc54a3aa0c766f9bd8a102269f15bdc4626de447013
[root@docker_host_0 ~]#
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker container ls -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                            NAMES
4b6078987966        registry:latest     "/entrypoint.sh /etc…"   5 seconds ago       Up 4 seconds        0.0.0.0:443->443/tcp, 5000/tcp   auth-repos
[root@docker_host_0 ~]#

    服务端推送镜像:

[root@docker_host_0 ~]# docker push repos.abc.com/centos:net
The push refers to repository [repos.abc.com/centos]
d69483a6face: Pushed
net: digest: sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66 size: 529
[root@docker_host_0 ~]#

    客户端登录并拉取镜像:

[root@docker_host_1 ~]# docker login -u testuser -p testpassword repos.abc.com
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# docker image rm repos.abc.com/centos:net
Untagged: repos.abc.com/centos:net
Untagged: repos.abc.com/centos@sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# docker pull repos.abc.com/centos:net
net: Pulling from centos
Digest: sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66
Status: Downloaded newer image for repos.abc.com/centos:net
[root@docker_host_1 ~]#

服务化

    将私有仓库运行为swarm服务,可以提供高可用与负载均衡,规模动态伸缩,以及所有群集具有的可控性。

    服务端若设置了TLS证书加密,则需要将签名证书与私钥通过docker secret命令转换为docker可识别的密码。

[root@docker_host_0 ~]# docker swarm init
Swarm initialized: current node (xq0bpbkwlm330dnrk4mijzff7) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-35s6bplzktc50note93vh9pmlbd2pqhgw7i752d2n1473zgp3q-edeegcggx16bs4q6y0vnmqpts 192.168.9.168:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker secret create repos.abc.com.crt /opt/certs/repos.abc.com.crt
solfgubitfxnpm3tjsr6eq02n
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker secret create repos.abc.com.key /opt/certs/repos.abc.com.key
oyd4s0eqn64nhukikml6pg0s2
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker secret ls
ID                          NAME                DRIVER              CREATED             UPDATED
solfgubitfxnpm3tjsr6eq02n   repos.abc.com.crt                       22 seconds ago      22 seconds ago
oyd4s0eqn64nhukikml6pg0s2   repos.abc.com.key                       6 seconds ago       6 seconds ago
[root@docker_host_0 ~]#

    以注册镜像运行服务,名称为serv-repos:

服务密码默认挂载为/run/secrets/目录下的同名文件,如abc.crt对应于/run/secrets/abc.crt。

[root@docker_host_0 ~]# docker container rm -f auth-repos
auth-repos
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker container ls -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@docker_host_0 ~]#
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker service create \
> --name serv-repos \
> --restart-condition any \
> --secret repos.abc.com.crt \
> --secret repos.abc.com.key \
> --mount type=bind,src=/opt/auth,dst=/auth,ro \
> -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
> -e REGISTRY_HTTP_TLS_CERTIFICATE=/run/secrets/repos.abc.com.crt \
> -e REGISTRY_HTTP_TLS_KEY=/run/secrets/repos.abc.com.key \
> -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
> -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/registry.htpasswd \
> --constraint 'node.hostname == docker_host_0' \
> --replicas 1 \
> -p 443:443 \
> registry:latest
0xaumjaq2pwq66txcqi3tr3wo
overall progress: 1 out of 1 tasks
1/1: running
verify: Service converged
[root@docker_host_0 ~]#
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
0xaumjaq2pwq        serv-repos          replicated          1/1                 registry:latest     *:443->443/tcp
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker container ls -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
951f31774da2        registry:latest     "/entrypoint.sh /etc…"   33 seconds ago      Up 32 seconds       5000/tcp            serv-repos.1.kw0udiv310eao0r27uaj0wzoi
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker service ps serv-repos
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
kw0udiv310ea        serv-repos.1        registry:latest     docker_host_0       Running             Running 35 seconds ago
[root@docker_host_0 ~]#
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# ss -atn | grep 443
LISTEN     0      128         :::443                     :::*
[root@docker_host_0 ~]#

    服务端登录并推送镜像:

[root@docker_host_0 ~]# docker login -u testuser -p testpassword repos.abc.com
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
[root@docker_host_0 ~]#
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker push repos.abc.com/centos:net
The push refers to repository [repos.abc.com/centos]
d69483a6face: Pushed
net: digest: sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66 size: 529
[root@docker_host_0 ~]#

    客户端登录并拉取镜像:

[root@docker_host_1 ~]# docker image rm repos.abc.com/centos:net
Untagged: repos.abc.com/centos:net
Untagged: repos.abc.com/centos@sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# docker login -u testuser -p testpassword repos.abc.com
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# docker pull repos.abc.com/centos:net
net: Pulling from centos
Digest: sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66
Status: Downloaded newer image for repos.abc.com/centos:net
[root@docker_host_1 ~]#

    用于保存镜像数据的后端存储驱动类型决定了注册的部署方式:

  • 若使用本地文件系统,包括非共享的本地源路径与数据卷,则应尽量以单副本方式部署注册,并以标签(label)约束(constraint)的方式指定注册所在节点,以确保推送的目标与拉取的来源一致,避免读写冲突。
  • 若使用网络分布式存储驱动,包括ceph,zfs,或第三方存储驱动(如阿里云OSS)等,则镜像数据的读写均使用相同的后端存储,注册可以部署为多副本模式,以提供规模的动态伸缩与服务的负载均衡功能。

前端代理

    通过代理服务器分发请求是生产环境中常用的部署方式,本节以nginx(tengine-2.3.0)为例:

  • 镜像数据存储至手动创建的本地命名数据卷images-data。
  • nginx配置文件与日志通过目录的方式挂载至容器,源路径分别为/opt/nginx/conf与/opt/nginx/logs。
  • ssl证书与用户认证文件通过目录的方式挂载至容器,源路径分别为/opt/nginx/certs与/opt/nginx/auth。

    编辑用于构建nginx镜像的dockerfile:

[root@docker_host_0 ~]# vi /opt/dockerfile-for-tengine
FROM centos:latest
ARG tmp_dir='/tmp'
ARG repo_key='http://mirrors.163.com/centos/RPM-GPG-KEY-CentOS-7'
ARG repo_src='http://mirrors.163.com/.help/CentOS7-Base-163.repo'
ARG repo_dst='/etc/yum.repos.d/CentOS-Base.repo'
ARG tengine_ver='2.3.0'
ARG tengine_src="http://tengine.taobao.org/download/tengine-${tengine_ver}.tar.gz"
ARG tengine_dst="tengine-${tengine_ver}.tar.gz"
ARG tengine_cfg_opts='--prefix=/usr/local/nginx \
                      --with-http_gzip_static_module \
                      --with-http_stub_status_module \
                      --with-http_ssl_module \
                      --with-http_slice_module \
                      --with-pcre'
ARG depend_rpms='gcc make openssl-devel pcre-devel'
RUN cd ${tmp_dir} \
    && cp -a ${repo_dst} ${repo_dst}.ori \
    && curl -L ${repo_src} -o ${repo_dst} \
    && curl -L ${tengine_src} -o ${tengine_dst} \
    && rpm --import ${repo_key} \
    && yum -y update --downloadonly --downloaddir=. \
    && yum -y install ${depend_rpms} --downloadonly --downloaddir=. \
    && yum -y install ./*.rpm \
    && useradd www -s /sbin/nologin \
    && tar axf ${tengine_dst} \
    && cd tengine-${tengine_ver} \
    && ./configure ${tengine_cfg_opts} \
    && make \
    && make install \
    && cd \
    && yum -y remove gcc make cpp \
    && yum clean all \
    && rm -rf ${tmp_dir}/*
EXPOSE 80/tcp 443/tcp
ENV PATH ${PATH}:/usr/local/nginx/sbin
CMD nginx -g "daemon off;"

    构建nginx镜像,名称为tengine_nginx:2.3.0:

[root@docker_host_0 ~]# docker build -f /opt/dockerfile-for-tengine -t tengine_nginx:2.3.0 .
...
[root@docker_host_0 ~]# docker image ls tengine_nginx:2.3.0
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
tengine_nginx       2.3.0               967940636cb9        About a minute ago   344MB
[root@docker_host_0 ~]#

    运行nginx镜像60秒,名称为t_nginx,并将nginx所需文件复制到宿主机:

[root@docker_host_0 ~]# docker run -dit --rm --name t_nginx tengine_nginx:2.3.0 bash -c 'timeout 60 nginx -g "daemon off;"'
6a38b246c5b82ec3d779d286188101c1dd9d70c237cc1369898be8857dda540b
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker container ls -a
CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS               NAMES
6a38b246c5b8        tengine_nginx:2.3.0   "bash -c 'timeout 60…"   6 seconds ago       Up 6 seconds        80/tcp, 443/tcp     t_nginx
951f31774da2        registry:latest       "/entrypoint.sh /etc…"   14 minutes ago      Up 14 minutes       5000/tcp            serv-repos.1.kw0udiv310eao0r27uaj0wzoi
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker exec -it t_nginx ls -l /usr/local/nginx
total 0
drwx------ 2 nobody root   6 Jun 13 00:27 client_body_temp
drwxr-xr-x 2 root   root 333 Jun 13 00:24 conf
drwx------ 2 nobody root   6 Jun 13 00:27 fastcgi_temp
drwxr-xr-x 2 root   root  40 Jun 13 00:24 html
drwxr-xr-x 1 root   root  58 Jun 13 00:27 logs
drwx------ 2 nobody root   6 Jun 13 00:27 proxy_temp
drwxr-xr-x 2 root   root  19 Jun 13 00:24 sbin
drwx------ 2 nobody root   6 Jun 13 00:27 scgi_temp
drwx------ 2 nobody root   6 Jun 13 00:27 uwsgi_temp
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker cp t_nginx:/usr/local/nginx/ /opt
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# ll /opt/nginx/
total 0
drwx------ 2 root root   6 Jun 13 00:27 client_body_temp
drwxr-xr-x 2 root root 333 Jun 13 00:24 conf
drwx------ 2 root root   6 Jun 13 00:27 fastcgi_temp
drwxr-xr-x 2 root root  40 Jun 13 00:24 html
drwxr-xr-x 2 root root  58 Jun 13 00:27 logs
drwx------ 2 root root   6 Jun 13 00:27 proxy_temp
drwxr-xr-x 2 root root  19 Jun 13 00:24 sbin
drwx------ 2 root root   6 Jun 13 00:27 scgi_temp
drwx------ 2 root root   6 Jun 13 00:27 uwsgi_temp
[root@docker_host_0 ~]#

    创建nginx证书与密码认证文件的挂载源路径:

[root@docker_host_0 ~]# mkdir -p /opt/nginx/{certs,auth}
[root@docker_host_0 ~]#

    设置ssl证书(先前已生成):

[root@docker_host_0 ~]# cp -a /opt/certs/* /opt/nginx/certs/
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# ll /opt/nginx/certs/
total 8
-rw-r--r-- 1 root root 1976 Jun 12 22:55 repos.abc.com.crt
-rw-r--r-- 1 root root 3272 Jun 12 22:55 repos.abc.com.key
[root@docker_host_0 ~]#

    创建认证文件/opt/nginx/auth/registry.htpasswd,用户名与密码分别为testuser与testpassword,加密方式为默认的MD5:

[root@docker_host_0 ~]# docker run --rm --entrypoint htpasswd registry:latest -bn testuser testpassword > /opt/nginx/auth/registry.htpasswd
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# ll /opt/nginx/auth/registry.htpasswd
-rw-r--r-- 1 root root 48 Jun 13 00:32 /opt/nginx/auth/registry.htpasswd
[root@docker_host_0 ~]#

    创建用于存储镜像的本地命名数据卷:

[root@docker_host_0 ~]# docker volume create images-data
images-data
[root@docker_host_0 ~]#

    编辑服务编排配置文件:

volumes.卷名.external配置选项的值为true,表示使用预先创建的命名数据卷。

version: "3.7"

services:
  registry:
    image: registry:2
    volumes:
      - type: volume
        source: images-data
        target: /var/lib/registry
    deploy:
      placement:
        constraints:
          - node.hostname == docker_host_0
      mode: replicated
      replicas: 1
      restart_policy:
        condition: any

  nginx:
    image: tengine_nginx:2.3.0
    volumes:
      - type: bind
        source: /opt/nginx/conf
        target: /usr/local/nginx/conf
        read_only: true
      - type: bind
        source: /opt/nginx/logs
        target: /usr/local/nginx/logs
      - type: bind
        source: /opt/nginx/certs
        target: /usr/local/nginx/certs
        read_only: true
      - type: bind
        source: /opt/nginx/auth
        target: /usr/local/nginx/auth
        read_only: true
    deploy:
      placement:
        constraints:
          - node.hostname == docker_host_0
      mode: replicated
      replicas: 1
      restart_policy:
        condition: any
    ports:
      - target: 443
        published: 443
        protocol: tcp
        mode: ingress

volumes:
  images-data:
    external: true

    编辑nginx配置文件:

user www www;
worker_processes auto;
pid logs/nginx.pid;
error_log logs/error.log warn;
worker_rlimit_nofile 51200;

events {
	use epoll;
	worker_connections 4096;
}

http {
	include mime.types;
	default_type application/octet-stream;
	server_names_hash_bucket_size 128;
	client_header_buffer_size 16k;
	large_client_header_buffers 4 32k;
	client_max_body_size 8m;
	access_log off;
	sendfile on;
	tcp_nopush on;
	tcp_nodelay on;
	keepalive_timeout 30;
	proxy_cache_methods POST GET HEAD;
	open_file_cache max=655350 inactive=20s;
	open_file_cache_valid 30s;
	open_file_cache_min_uses 2;

	gzip on;
	gzip_min_length 1k;
	gzip_buffers 8 8k;
	gzip_http_version 1.0;
	gzip_comp_level 4;
	gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php;
	gzip_vary on;
	server_tokens off;

	log_format main	'$remote_addr\t$upstream_addr\t[$time_local]\t$request\t'
					'$status\t$body_bytes_sent\t$http_user_agent\t$http_referer\t'
                    '$http_x_forwarded_for\t$request_time\t$upstream_response_time\t$remote_user\t'
					'$request_body';

	map $http_upgrade $connection_upgrade {
		default upgrade;
		'' close;
	}

	map $upstream_http_docker_distribution_api_version $docker_distribution_api_version {
		'' 'registry/2.0';
	}

	upstream docker-registry {
		server registry:5000;
	}

	server {
		listen 443 ssl;
		server_name repos.abc.com;
		ssl_certificate /usr/local/nginx/certs/repos.abc.com.crt;
		ssl_certificate_key /usr/local/nginx/certs/repos.abc.com.key;
		ssl_protocols TLSv1.1 TLSv1.2;
		ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
		ssl_prefer_server_ciphers on;
		ssl_session_cache shared:SSL:10m;

		charset utf-8;
		client_max_body_size 0;
		chunked_transfer_encoding on;

		location /v2/ {
			if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
				return 404;
			}

			auth_basic "Restricted access to local Docker Registry";
			auth_basic_user_file /usr/local/nginx/auth/registry.htpasswd;

			add_header 'Docker-Distribution-Api-Version' $docker_distribution_api_version always;
			proxy_pass http://docker-registry;
			proxy_set_header Host $http_host;
			proxy_set_header X-Real-IP $remote_addr;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			proxy_set_header X-Forwarded-Proto $scheme;
			proxy_read_timeout 900;
		}

		access_log logs/registry-access.log main;
	}
}

    测试nginx配置文件:

[root@docker_host_0 ~]# docker run -it --rm \
> --mount type=bind,src=/opt/nginx/conf/nginx.conf,dst=/usr/local/nginx/conf/nginx.conf,ro \
> --mount type=bind,src=/opt/nginx/certs,dst=/usr/local/nginx/certs,ro \
> --mount type=bind,src=/opt/nginx/auth,dst=/usr/local/nginx/auth,ro \
> --add-host registry:127.0.0.1 \
> tengine_nginx:2.3.0 \
> bash -c 'nginx -t'
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@docker_host_0 ~]#

    部署服务,名称为proxied-registry(确保当前宿主机以开启swarm模式,且为管理角色):

[root@docker_host_0 ~]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
xq0bpbkwlm330dnrk4mijzff7 *   docker_host_0       Ready               Active              Leader              18.09.6
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker service rm serv-repos
serv-repos
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker stack deploy -c /opt/registry-with-tengine.yml proxied-registry
Creating network proxied-registry_default
Creating service proxied-registry_registry
Creating service proxied-registry_nginx
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker stack ls
NAME                SERVICES            ORCHESTRATOR
proxied-registry    2                   Swarm
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker service ls
ID                  NAME                        MODE                REPLICAS            IMAGE                 PORTS
7trg1afndzjb        proxied-registry_nginx      replicated          1/1                 tengine_nginx:2.3.0   *:443->443/tcp
q8r85uscnwdx        proxied-registry_registry   replicated          1/1                 registry:2
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# ss -atn | grep 443
LISTEN     0      128         :::443                     :::*
[root@docker_host_0 ~]#

    服务端登录并推送镜像:

若登录失败,终端显示"Error response from daemon: login attempt to https://repos.abc.com/v2/ failed with status: 500 Internal Server Error",且nginx错误日志提示"...6 crypt_r() failed (22: Invalid argument)...",表示用于生成密码的加密算法(如bcrypt)不受当前nginx版本的支持,需要更换其他加密算法(如MD5或SHA1等)。

[root@docker_host_0 ~]# docker login -u testuser -p testpassword repos.abc.com
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker push repos.abc.com/centos:net
The push refers to repository [repos.abc.com/centos]
d69483a6face: Pushed
net: digest: sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66 size: 529
[root@docker_host_0 ~]#

    查看镜像仓库与标签:

curl命令的--user选项用于指定请求登录的用户名与密码,以冒号分隔。

[root@docker_host_0 ~]# curl --cacert /opt/certs/repos.abc.com.crt --user testuser:testpassword -X GET https://repos.abc.com/v2/_catalog -i
HTTP/1.1 200 OK
Server: Tengine
Date: Thu, 13 Jun 2019 00:46:07 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 28
Connection: keep-alive
Docker-Distribution-Api-Version: registry/2.0
X-Content-Type-Options: nosniff

{"repositories":["centos"]}
[root@docker_host_0 ~]#
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# curl --cacert /opt/certs/repos.abc.com.crt --user testuser:testpassword -X GET https://repos.abc.com/v2/centos/tags/list -i
HTTP/1.1 200 OK
Server: Tengine
Date: Thu, 13 Jun 2019 00:46:16 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 33
Connection: keep-alive
Docker-Distribution-Api-Version: registry/2.0
X-Content-Type-Options: nosniff

{"name":"centos","tags":["net"]}
[root@docker_host_0 ~]#

    客户端登录并拉取镜像:

[root@docker_host_1 ~]# docker login -u testuser -p testpassword repos.abc.com
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
[root@docker_host_1 ~]#
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# docker image rm repos.abc.com/centos:net
Untagged: repos.abc.com/centos:net
Untagged: repos.abc.com/centos@sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# docker pull repos.abc.com/centos:net
net: Pulling from centos
Digest: sha256:ca58fe458b8d94bc6e3072f1cfbd334855858e05e1fd633aa07cf7f82b048e66
Status: Downloaded newer image for repos.abc.com/centos:net
[root@docker_host_1 ~]#

参考

https://docs.docker.com/registry/
https://github.com/docker/distribution-library-image
https://github.com/docker/docker-ce/blob/master/components/cli/vendor/github.com/docker/docker/registry/config.go
https://docs.docker.com/compose/compose-file/

 

 

转载于:https://my.oschina.net/superwjc/blog/3061394

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值