Docker—11章(镜像中心)


镜像中心

Docker Hub 与阿里云都是 Docker 的公网镜像中心,用户可以将自己的镜像 push 到公网镜像中心中自己的镜像仓库,并可将仓库设置为私有库,使他人无法看到,更无法 pull,以保证镜像的安全性。

不过,在实际生产中为了保障镜像的安全性,为了避免由于网络带宽或网速等问题而影响到镜像的拉取或推送,公司一般不会使用公网镜像中心,而是在公司内部搭建一个私有镜像中心

1. 发布镜像到 Docker Hub

下面详细介绍如何将前面已经构建好的 hello-my-world 镜像发布到 Docker Hub

1.1 镜像仓库的创建

1.1.1 注册账号

首先要注册一个 Docker Hub 的账号。

1.1.2 镜像仓库的创建

对于 Docker Hub 中镜像仓库的创建,有两种方式。一种方式是手工创建,在登录到 DockerHub 官网的相应账户后,在 Repositoris 下,通过 create repository 按钮创建

这种方式需要通过邮箱确认

还有一种方式是自动创建镜像仓库。直接通过提交的镜像的<repository>创建相应的仓库。该方式简单方便。下面的操作就是采用的这种方式。

1.2 Docker客户端操作

1.2.1 登陆Docker Hub

对于非登录客户端,只能从镜像中心 pull 公共镜像,对于私有镜像是不能 pull 的,当然也不能将镜像 push 到镜像中心。在 Docker 引擎上使用 docker login 命令可实现镜像中心的登录

登陆

也可采用如下方式登录。

1.2.2 复制并重命名镜像

通过docker tag命令可以对原有镜像进行复制并重命名。这个重命名的镜像的<repository>中必须采用<username>/<software-name>格式,且<username>必须是登录 Docker Hub 的用户名。

  1. 先创建一个目录:/root/hdw

  2. 在hdw目录中,创建hello.c文件;文件内容如下

    #include<stdio.h>
    int main(){
     printf("hello docker hub world\n");
     return 0;
    }
    
  3. 编译hello.c文件

    gcc --static -o hello hello.c
    

  4. 运行

  5. 编写Dockerfile文件

    FROM scratch
    ADD hello /
    CMD ["/hello"]
    
  6. 构建镜像

    hello-my-world镜像

接下来就可以把你的hello-my-world镜像上传到自己的docker hub上去

复制镜像

  • nxz/hello-my-world:1.0 是目标镜像的名称和标签。这里使用了 nxz/hello-my-world 作为镜像的名称,
  • 1.0 作为标签。
  • nxz 是目标镜像的仓库名hello-my-world镜像的名称1.0 是标签。

对于本例,为了方便演示后面的效果,这里多复制出几个镜像

1.2.3 推送镜像

使用 docker push 命令将镜像推送到 Docker Hub

注意:此处要想推送成功,用户必须先登陆;登陆过程见本章1.2.1

也将另外几个镜像推送到 Docker Hub

1.2.4 查看 Docker Hub

Docker Hub 页面中点击 Repositories 导航栏即可看到 push 来的镜像仓库。

注意,由于我之前使用的是nxz/XXX来推送,我自己的用户名是yijieliu,所以之前的推送都无法查看,只有yijieliu/xxx才能查看到

点击该仓库,则可看到其详情。

1.2.5 删除镜像

Tags 页面中选中要删除的镜像,点击 Delete 按钮即可弹出镜像删除确认对话框。

直接点击 Confirm Delete 确认删除即可。

1.2.6 删除仓库

Settings 页面的最下面有 Delete repository 按钮

点击该按钮后弹出删除确认对话框。

该对话框提示,该删除将无法撤回。需要在文本框中按照提示输入确认信息。然后点击Delete 即可删除。

1.2.7 登出 Docker Hub

通过 docker logout 命令可以从 Docker 引擎中退出登录的Docker Hub账号。

2. 发布镜像到腾讯云

2.1 腾讯云设置

首先登陆腾讯云:腾讯云 产业智变·云启未来 - 腾讯 (tencent.com)

然后选择服务:

服务选择

实例管理

实例选择好之后,需要在这下面设置初始密码:

这个密码要记住,后面测试使用腾讯云输入的密码就是这个,如果忘记了密码,这里更多选项可以选择重置密码

设置密码完成

这里我选择的是带有个人版本的广州的实例。

新建命名空间

命名空间建立以后,选择新建镜像仓库。

新建仓库

新建镜像仓库

选择快捷指令,后面可以使用docker命令

接下来就可以进行测试了

2.2 Docker发布镜像到腾讯云

  1. 登陆

    docker login ccr.ccs.tencentyun.com --username=你的ID
    

  2. 向 Registry 中推送镜像

    docker tag hello-my-world:latest ccr.ccs.tencentyun.com/cqnxz/hello-my-world:1.0
    

    复制镜像并重命名

    docker push ccr.ccs.tencentyun.com/cqnxz/hello-my-world:1.0
    

    推送镜像

  3. 查看腾讯云

  4. 删除镜像很简单,直接操作即可

3. 私有镜像中心基础知识

3.1 HTTP/HTTPS协议

3.1.1 协议

HTTP HTTPS 协议都是客户端浏览器和服务器间的一种约定,约定如何将服务器中的信息下载到本地,并通过浏览器显示出来。

不同的是,HTTP 协议是一种明文传输协议,其对传输的数据不提供任何加密措施。而HTTPS 协议则是通过 SSL/TLS 为数据加密,以保障数据的安全性。

通常情况下,HTTP 会直接与运输层的 TCP 进行通信,默认使用 80 端口号。但在使用SSL/TLS 协议的 HTTPS 后,就演变成了直接与运输层的 SSL/TLS 进行通信,再由 SSL/TLSTCP进行通信。即 HTTPS 是间接与 TCP 进行通信的。HTTPS 默认使用 443 端口号

3.1.2 SSL/TLS

SSLSecure Sockets Layer,安全套接字协议

TLSTransport Layer Security,传输层安全协议

它们主要用于保障在 Internet 上数据传输的安全性与完整性

3.1.3 加密验证方式

HTTP 协议通过明文传输存在三大风险:

  • 被窃听的风险

  • 被篡改的风险

  • 被冒充的风险

    HTTPS 协议通过用户身份验证与传输加密,大大降低了 HTTP 中的这些风险

    HTTPS 协议中的身份验证采用的是非对称加密验证方式,而传输加密采用的则是对称加密验证方式。

  • 对称加密验证:加密与解密使用的密钥相同。例如,登录使用的账号/密码就属于对称加密验证(用户提交的账号/密码与保存在服务器中的账号/密码必须相同,验证才能成功)。

  • 非对称加密验证:加密与解密使用的密钥不同。其本质上就是数据算法。主要有三类算法:因子分解算法、离散对数算法、椭圆曲线算法。其中,因了分解算法使用最为广泛\

3.1.4 公钥与私钥

非对称加密验证中需要一对密钥。其中一个用于加密,一个用于解密,即所谓的公钥与私钥。

  • 公钥:可以公开的密钥,是发放给其他人的密钥

  • 私钥:非公开的密钥,是只有加密者自己保存的密钥

    公钥与私钥都可用于加密/解密。

  • 公钥加密,私钥解密:称为信息加密与信息解密

  • 私钥加密,公钥解密:称为数字签名与签名验证

3.2 以故事方式开始HTTPS工作原理

以“特工张三与总部李四的通信故事”来说明 HTTPS 的工作原理。

3.2.1 明文通信过程

明文通信过程

存在的问题是,信息可能被劫持(数据被窃取、被篡改),数据非常不安全。

3.2.2 使用数字签名加密

整个通信过程包含两个阶段:通信关系建立阶段与通信阶段。

使用数字签名加密通信之通信关系建立过程

使州数字答名加密通信之通信时程

3.2.3 钓鱼问题

钓鱼问题

3.2.4 使用数字证书

整个通信过程包含三个阶段:通信基础构建阶段、通信关系建立阶段与通信阶段。

使用数字证书通信之通信基础构建过程

使用数字证书通信之通信关系建立过程

使用数字证书通信之通信过程

3.2.5 对称加密通信

整个通信过程包含三个阶段:通信基础构建阶段、通信关系建立阶段与通信阶段。通信阶段中的身份验证采用非对称加密验证方式,通信过程采用对称加密验证方式。

对称加密通信之通信基础构建过程

对称加密通信之通信关系建立过程

对称加密通信之通信过程

3.2.6 HTTPS 通信原理

HTTPS工作原理之通信基础构建过程

HTTPS工作原理之通信关系建立过程

HTTPS工作原理之通信过程

3.3 HTTPS重要概念

3.3.1 数字证书

数字证书,也称为 SSL/TLS 证书,是互联网通讯中标志通讯各方身份信息的一串数字。提供了一种在 Internet 上验证通信实体身份的方式。它是由 CA(Certificate Authority,证书权威认证机构,证书中心)颁发的一种身份证明。它里面包含了该通讯方的公钥、证书有效时间、域名及 CA 的数字签名等。数字证书的一个非常重要的作用就是“防钓鱼”。

全球的 CA(权威证书中心)一共也没有几个,即全球可以颁发数字证书的机构并不多。而像我国阿里、腾讯等也都属于这些大的权威证书中心的代理机构。我们可以通过他们来申办证书,而他们本身并不具有生成证书的权限。

3.3.2 根证书

数字证书是由 CA(Certificate Authority,证书权威认证机构,证书中心)颁发的一种身份证明,是通过 CA 私钥加密过的。所以,客户端必须具有 CA 公钥才能解密要访问平台服务器的数字证书。而这个 CA 公钥就被称为 CA 根证书,也称为根证书。

当然,数字证书除了权威证书中心可申请到外,也可自己生成。但自己生成的证书并没有在客户端系统中,这时就需要用户在客户端先安装数字证书,并将其添加到相应的“信任”状态才可。这就是我们平时如果要在本地电脑中打开网银平台对自己的电子银行进行操作之前,会先提示安装根证书的原因。这个安装根证书的提示,就包含网银的数字证书与 CA 根证书。

3.3.3 数字摘要

数字摘要是将任意长度的消息变成固定长度的短消息。数字摘要就是利用了 Hash 函数的单向性,将需要加密的明文“摘要”成一串 128 位长度数字串。这个数字串又称为数字指纹。其单向性体现在:不同明文“摘要的结果”一定是不同的,相同明文“摘要的结果”必定是一致。但摘要结果无法计算出其原始明文。

3.3.4 数字签名

数字签名,是只有信息的发送者才能产生的别人无法伪造的一段数字串。它是一种类似写在纸上的手写物理签名,用于鉴别数字信息是否被篡改的方法。
数字签名是非对称密钥技术与数字摘要技术的应用。使用私钥对明文的数字摘要加密,形成数字签名;使用公钥对数字签名解密,称为签名验证。

3.4 htpasswd命令

registry 私有镜像中心中默认是没有用户认证功能的,可通过 htpasswd 来实现用户认证。

3.4.1 简介

htpasswd 是开源 Web 服务器 Apache HTTP Server 的内置工具,用于创建、更新 HTTP基本认证的密码文件。

3.4.2 安装 httpd-tools

htpasswd 命令在 Linux 中默认是没有的,需要先行安装。而该工具在 httpd-tools 工具包中,所以需要先安装该工具包。

yum install -y httpd-tools

3.4.3 创建文件并添加用户

为方便演示,在/root mkdir 一个目录 auth,在其中存放生成的认证文件

该命令的含义如下:

  • -B 参数指定使用 bcrypt 加密算法。
  • -b 参数表示将用户名和密码一起提供。
  • -c 选项用于创建一个新的密码文件。这意味着如果 htpasswd.user 文件已经存在,则该文件将被覆盖并重新创建。如果省略 -c 选项,那么新的用户名和密码将追加到现有的文件中,而不会覆盖它。
  • htpasswd.user 是要存储用户名和密码的文件名。
  • zhangsan 是要创建的用户名。
  • 123 是要分配给用户的密码。

将字符串 zhangsan 123 分别指定为用户名与密码,并写入到 auth 目录中的htpasswd.user 文件中。

查看 htpasswd.user 文件内容,可以看到该用户名与密码,只不过密码是加密过的。

3.4.4 再添加两用户

再写入两对用户名与密码,此时无需再写-c 选项了

3.4.5 修改密码

修改密码与添加密码使用方式相同:若指定的用户名不存在,则为添加;若指定的用户名存在,则为密码修改。

3.4.6 删除用户名与密码

删除用户名与密码,使用选项-D() Delete the specified user).

用户名 lisi 消失了。

3.4.7 使用-n 选项创建文件

使用-n 选项,再配合重定向符也可将用户密码写入到文件。例如,下面的命令将用户名与密码写入到了当前目录的 authfile 中了。

这种情况下若要添加和修改密码,则可通过追加重定向符来完成。

3.5 容器的退出状态码

Docker Daemon 通过退出状态码向用户反馈容器中应用的退出方式。

3.5.1 状态码分类

容器退出状态码是[0, 255]范围内的整数,分为三类:0[1,128][129,255]

  • 状态码 0 表示容器中应用是正常退出,例如通过 docker stop 命令退出/bin/bash,或 docker引擎关闭后引发的容器退出/bin/bash 等。
  • [1,128]范围内的状态码,非正常退出状态,表示容器内部运行错误引发的容器无法启动,或应用运行出错。
  • [129,255]范围内的状态码,非正常退出状态,表示容器接收到终止信号而退出

常见的状态码如下:

3.5.2 状态码 1

常见有两种情况可能会引发容器的退出状态码为 1。

  • 应用程序内部错误。例如,分母为 0,内存溢出,数组下标越界等。
  • Dockerfile 中的无效引用。即 Dockerfile 中引用了不存在的文件,导致容器无法启动。

3.5.3 状态码 125

容器启动后要执行指定的[command],但[command]没有运行成功。没有成功的原因通常是[command] 引用了未定义的变量,或执行了没有权限的命令等。

3.5.4 状态码 126

容器启动后要执行指定的[command],但[command]没有运行成功。没有成功的原因通常是该[command]的执行缺少依赖

例如,Dockerfile 中要运行 CMD [“java”,”-jar”,”demo.jar”],而该容器中没有 JDK

3.5.5 状态码 127

容器启动后要执行指定的[command],但[command]没有运行成功。没有成功的原因通常是该[command]中引用了不存在的文件或目录

例如,Dockerfile 中要运行 CMD [“java”,”-jar”,”demo.jar”],而该容器中没有 demo.jar

3.5.6 状态码 128

由自己开发的容器内的代码触发了退出命令并给出了退出状态码,但状态码不在 0-255范围内。此时返回给用户的退出状态码为 128。

3.5.7 状态码 130

当容器中的应用接收到来自操作系统的终止信号时,应用会立即退出,并返回给用户130 状态码。

3.5.8 状态码 137

当容器中的应用接收到来自 dockerd 强制终止信号时会立即退出,并返回给用户 137状态码。

3.5.9 状态码 143

当容器接收到来自 dockerd优雅终止信号时,如果当前容器并没有用户访问,那么容器会立即退出,并返回给用户 143 状态码。如果容器正好有用户访问,那么 dockerd 会等待10s。10s 后会向容器发送 kill 信号,此时返回给用户 137 状态码。

3.5.10 退出状态码查看方式

查看退出状态码的方式有两种:docker ps –a docker inspcet

docker ps –a
#或者
docker inspcet 容器名

3.6 容器的重启策略

docker 容器启动后并不会永远处于运行状态,各种意外都可能会导致容器退出。在生产环境下容器退出后采用手动重启方式肯定是非常低效或不可行的。而 Docker 引擎提供了容器的重启策略,通过在容器创建时指定--restart 选项不同的值,来达到不同的重启效果。其取值有以下几种:

3.6.1 no

默认策略,在容器退出时不重启容器。

3.6.2 on-failure[:n]

在容器非正常退出时,即退出状态码非 0 的情况下才会重启容器。其后还可以跟一个整型数,表示重启的次数。

3.6.3 always

只要容器退出就会重启容器。

3.6.4 unless-stopped

只要容器退出就会重启容器,除非通过 docker stopdocker kill命令停止容器。

4. distribution 私有镜像中心

一般私有镜像中心是专门的一台服务器,不用作平时的 Docker 容器的运行管理。相对于该镜像中心,其它要对其进行 push pull 操作的 Docker 主机,就称为 Docker 客户端。

4.1 镜像中心搭建

4.1.1 安装 docker-distribution

yum install -y docker-distribution

4.1.2 查看安装的文件

通过 rpm 命令可查看到该安装包安装的内容。

rpm -ql docker-distribution
  • -q 表示查询已安装的软件包。
  • -l 表示列出软件包中的文件。

  • /etc/docker-distribution/registry/config.yml 是镜像中心的核心配置文件
  • /usr/bin/registry 是安装到/usr/bin 目录中的一个 registry 命令
  • /usr/lib/systemd/system/docker-distribution.service 表示 docker-distribution 是个服务
  • /usr/share/doc/*是所有文档
  • /var/lib/registry 是镜像的保存目录

4.1.3 启动镜像中心

docker-distribution 是作为服务出现的,所以使用服务启动方式来启动它。

systemctl start docker-distribution

4.2 Docker客户端操作

私有镜像中心搭建成功了,Docker 客户端就可以向其中 push pull 镜像了

4.2.1 修改 daemon.json 文件

默认情况下,为了保证安全,Docker 客户端都采用的是 https 提交各种请求,例如,登录请求、pull 请求、push 请求等。但私有镜像中心默认不支持 https 协议。所以需要修改 Docker客户端,使其提交 http 请求。修改方式是:在 Docker 客户端的/etc/docker/daemon.json 文件中添加如下内容,指定镜像中心的地址是安全的。

4.2.2 重启 docker 引擎

配置文件修改了,需要重启 docker 引擎,以加载新的配置。

systemctl restart docker

4.2.3 登录私有镜像中心

注意:此处的账号密码可以写任意

4.3.4 复制并重命名镜像

通过 docker tag 命令可以对原有镜像进行复制并重命名。这个重命名的镜像的<repository>中需要采用<domain-name>/<software-name>格式。

再复制两个镜像。

4.3.5 推送镜像

4.3.6 查看镜像中心

通过 http://<私有镜像中心 IP>:5000/v2/_catalog 可查看到私有镜像中心中包含的所有仓库列表

curl -XGET http://你的私有镜像IP:5000/v2/_catalog

通过 http://<私有镜像中心 IP>:5000/v2/<repository>/tags/list 可查看指定仓库的 tag 列表

curl -XGET http://你的私有镜像IP:5000/v2//tags/list

4.3.7 登出私有镜像中心

docker logout 私有镜像中心IP:端口

4.3 删除镜像

4.3.1 修改容器配置

docker-distribution 私有库默认是不支持镜像删除的,需要修改镜像中心的配置文件/etc/docker-distribution/registry/config.yml。在 storage 节点下加入 delete: enabled: true

修改过文件后,重启 docker-distribution 服务。

systemctl restart docker-distribution

4.3.2 获取镜像 digest

该删除操作仅支持根据镜像的 Digest 删除,所以首先要获取到该镜像的 digest。当然,获取镜像 digest 的方式有两种:一种是先将镜像下载到本地,在本地通过命令查看;一种是直接通过 Http 请求获取。

第一种方式:下载到本地再通过 docker images --digests 命令查看。

第二种方式:直接通过 Http 请求获取。

通过 http://<私有镜像中心 IP>:5000/v2/<repository>/manifests/<tag>可查看,但该请求在提交时需要携带--header "Accept:application/vnd.docker.distribution.manifest.v2+json“请求头信息。在响应头的 Docker-Content-Digest 属性中携带着有镜像的 Digest

curl --header "Accept:application/vnd.docker.distribution.manifest.v2+json" -I -XGET http://私有镜像中心IP:5000/v2/hmyw/manifests/1.0

4.3.3 删除镜像

通过提交 Delete 请求 http://<私有镜像中心 IP>:5000/v2/<repository>/manifests/<digest>
删除指定的镜像。不过需要注意的是,该<digest>镜像可能有多个<tag>,其会删除所有该<digest>的镜像。

curl -I -XDELETE http://私有镜像中心IP:5000/v2/hmyw/manifests/sha256:02d54a178ee1fa488fb3b907734b4f8a4c69a0041c0f983fce315b162cafa273

此时再查看该仓库中的 tags,发现已经被删除了。

4.3.4 垃圾清理

在删除过镜像后,在镜像存放目录下的 docker/registry/v2/blobs 目录下仍保留了大量删除镜像相关的数据,形成了垃圾数据。这些数据最好清理掉。

而清理这些数据,需要使用 docker-distribution 内部提供的 registry garbage-collect 命令,且该命令需要提供镜像中心的配置文件 config.yml 作为参数。

 registry garbage-collect /etc/docker-distribution/registry/config.yml 

5. registry 私有镜像中心(HTTP)

5.1 镜像中心搭建

5.1.1 拉取镜像

Registry 私有镜像中心的本质其实就是一个运行中的容器,该容器的镜像为 registry。截止目前,该 registry 镜像共有两个大的版本:1.0 与 2.0。latest 版本为 2.0 版本。所以,首先要拉取 registry 镜像到本地。

5.1.2 创建用户密码文件

默认情况下创建好的私有镜像中心对于任何用户都是可以 push 的,这肯定是不安全的。所以,这里在启动镜像中心之前,先创建一个用于保存用户名与密码的文件。这里要使用Apachehtpasswd 命令创建用户名与密码。

在任何目录中 mkdir 一个目录 auth,专门用于存放用户信息。本例选择在/root 目录下创建 auth 目录。然后再将字符串 zhangsan111 分别指定为用户名与密码,并写入到auth 目录中的htpasswd.user文件中。

查看 htpasswd.user 文件内容,可以看到该用户名与密码,只不过密码是加密过的。

5.1.3 启动镜像中心容器

创建并启动 registry 镜像的容器。默认情况下被客户端 push 来的镜像会被保存在/var/lib/registry 中。

docker run --name myregistry \
--restart always \
-v /var/lib/registry:/var/lib/registry \
-v /root/auth:/auth \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd.user" \
-dp 5000:5000 \
registry

5.1.4 windows浏览器访问

在浏览器中通过 http://私有镜像IP:5000/v2/_catalog 地址访问查询镜像中心中的仓库,如果可以登录进去,则说明私有镜像中心搭建成功。注意,是 http 请求。

5.2 Docker客户端操作

registry 私有镜像中心搭建成功了,Docker 客户端就可以对其进行操作了。

5.2.1 修改 daemon.json 文件

默认情况下,为了保证安全,Docker 客户端都采用的是 https 提交各种请求,例如,登录请求、pull 请求、push 请求等。但私有镜像中心不接受 https 请求。所以需要告诉 Docker客户端该镜像中心地址是安全的,这样 Docker 客户端将会自动采用 http 请求方式。而对Docker 客户端的告知方式是,手工修改 Docker 客户端的/etc/docker/daemon.json 文件。

在文件中添加如下内容:

5.2.2 重启 docker 引擎

配置文件修改了,需要重启 docker 引擎,以加载新的配置。

systemctl restart docker

5.2.3 登录私有镜像中心

docker login -u zhangsan 私有镜像中心IP:5000

5.2.4 复制并重命名镜像

通过 docker tag 命令可以对原有镜像进行复制并重命名。这个重命名的镜像的<repository>中需要采用<domain-name>/<username>/<software-name>格式,且<username>是登录镜像中心的用户名。

5.2.5 推送镜像

再将另外两个镜像也 push 了。

5.2.6 查看镜像中心

通过 http://<私有镜像中心 IP>:5000/v2/_catalog 可查看到私有镜像中心中包含的所有仓库列表。

curl -u 用户名:密码 -XGET http://镜像中心IP:5000/v2/_catalog

通过 http://<私有镜像中心 IP>:5000/v2/<repository>/tags/list 可查看指定仓库的 tag 列表。

curl-u  用户名:密码 -XGET http://镜像中心IP:5000/v2/zhangsan/hw/tags/list

5.2.7 登出私有镜像中心

5.3 删除镜像

5.3.1 修改容器配置

Registry 私有库默认是不支持镜像删除的,需要修改镜像中心容器的文件系统中的配置文件/etc/docker/registry/config.yml

storage 节点下加入 delete: enabled: true

修改过文件后,重启容器。

5.3.2 获取镜像 digest

该删除操作仅支持根据镜像的 Digest 删除,所以首先要获取到该镜像的 digest

5.3.3 删除镜像

通过提交 Delete 请求 http://<私有镜像中心 IP>:5000/v2/<repository>/manifests/<digest>删除指定的镜像。不过需要注意的是,该<digest>镜像可能有多个<tag>,其会删除所有该<digest>的镜像。

curl -u 用户名:密码 -I -XDELETE http://私有镜像中心IP:5000/v2//manifests/

此时再查看该仓库中的 tags,发现已经被删除了。

curl -u  用户名:密码 -XGET http://镜像中心IP:5000/v2/zhangsan/hw/tags/list

5.3.4 垃圾清理

在删除过镜像后,在镜像存放目录下的 docker/registry/v2/blobs 目录下仍保留了大量删除镜像相关的数据,形成了垃圾数据。这些数据最好清理掉。而清理这些数据,需要使用 registry 容器内部提供的 registry garbage-collect 命令,且该命令需要提供 registry 的配置文件 config.yml 作为参数。

6. registry 私有镜像中心(HTTPS)

6.1 OpenSSL生成SSL证书

申请 SSL 证书需要申请者具有自己的域名,对于初学习者来说可能不是所有人都具备的。在学习阶段,使用 OpenSSL 也可以自己生成 SSL 证书。

6.1.1 安装 OpenSSL

OpenSSL 是一个开源的软件库,SSL 标准的工业化实现。可通过 yum 命令进行安装

yum install -y openssl-devel

安装完毕后可通过openssl version命令来查看。

6.1.2 创建证书目录

在任意目录下创建一个 cert 目录,用于存放 SSL 证书。

若要让证书中心 CA 为我们生成证书,必须要先有 CA。创建证书中心 CA 主要就是创建CA 的私钥与证书。

6.1.3 创建证书中心 CA

  1. 创建 CA 的私钥

    首先要创建证书中心的私钥。

    openssl genrsa -out ca.key 4096
    
    • openssl: 是 OpenSSL 工具的命令行接口。
    • genrsa: 是 OpenSSL 命令的子命令,用于生成 RSA 密钥对。
    • -out ca.key: 指定生成的私钥文件的输出路径和文件名,这里是 ca.key。私钥文件通常使用 .key.pem 后缀。
    • 4096: 指定生成的 RSA 密钥的位数,这里是 4096 位。较高的位数提供更高的安全性,但也会增加生成时间和密钥操作的计算量。

    此时在当前目录下就生成了 ca.key 文件。可以查看生成私钥的具体内容。

  2. 创建 CA 的证书

    openssl req -x509 -new -nodes -sha512 -days 3650 \
    -subj "/C=CN/ST=Beijing/L=Beijing/O=CA/OU=CAUnit/CN=cacn.com" \
    -key ca.key \
    -out ca.crt
    
    • openssl: 是 OpenSSL 工具的命令行接口。
    • req: 是 OpenSSL 命令的子命令,用于生成证书请求 (CSR) 或自签名证书。
    • -x509: 指定生成自签名证书。
    • -new: 指定生成新的证书,而不是基于现有的证书请求。
    • -nodes: 指定不加密生成的私钥。
    • -sha512: 指定使用 SHA-512 哈希算法来签名证书。
    • -days 3650: 指定证书的有效期限,这里是 3650 天,即 10 年。
    • -subj "/C=CN/ST=Beijing/L=Beijing/O=CA/OU=CAUnit/CN=cacn.com": 指定证书的主题字段信息,包括国家、省/州、城市、组织、组织单位和通用名称 (Common Name)。
    • -key ca.key: 指定用于签名证书的私钥文件路径和文件名,这里是 ca.key
    • -out ca.crt: 指定生成的证书文件的输出路径和文件名,这里是 ca.crt。证书文件通常使用 .crt.pem 后缀。

    此时在当前目录下就生成了 ca.crt 文件。可以查看生成证书的具体内容。

6.1.4 创建申请者证书

  1. 进入到 cert 目录

    openssl genrsa -out xxx.com.key 4096
    

  2. 生成请求文件

要生成正式的数字证书文件之前,需要先生成一个包含申请者自身个人信息的请求文件csr,将来的证书文件中的申请者信息就来自于该文件。

openssl req -sha512 -new -key xxx.com.key -out xxx.com.csr
  • openssl: 是 OpenSSL 工具的命令行接口。
  • req: 是 OpenSSL 命令的子命令,用于生成证书请求 (CSR) 或自签名证书。
  • -sha512: 指定使用 SHA-512 哈希算法来生成证书请求的摘要。
  • -new: 指定生成新的证书请求。
  • -key xxx.com.key: 指定用于生成证书请求的私钥文件路径和文件名,这里是 xxx.com.key。私钥文件应该是之前生成的与证书请求相关联的私钥。
  • -out xxx.com.csr: 指定生成的证书请求文件的输出路径和文件名,这里是 xxx.com.csr。CSR 文件通常使用 .csr.pem 后缀。

此时在当前目录下就生成了 server.csr 文件。可以查看 server.csr 文件内容。

  1. 生成 v3.ext 文件

    v3.ext 文件中,最重要的修改是 subjectAltName,要指定为当前的主机 IP

    cat > v3.ext <<-EOF
    authorityKeyIdentifier=keyid,issuer
    basicConstraints=CA:FALSE
    keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
    extendedKeyUsage = serverAuth
    subjectAltName = IP: 192.168.254.131
    [alt_names]
    DNS.1=xxx.com
    DNS.2=xxx.cn
    EOF
    

    此时在当前目录下就生成了 v3.ext 文件

  2. 生成申请者证书

    openssl x509 -req -sha512 -days 3650 \
    -extfile v3.ext \
    -CA ca.crt -CAkey ca.key -CAcreateserial \
    -in xxx.com.csr \
    -out xxx.com.crt
    

    可以查看生成的证书文件 xxx.com.crt,只不过是加过密的。

  3. 重命名证书名

crt 文件重命名为 cert。因为默认情况下,docker .crt 文件识别为 CA 证书,将.cert识别为用户生成的证书。当然,这个重命名也是通过 openssl 命令完成的。

openssl x509 -inform PEM -in xxx.com.crt -out xxx.com.cert

至此在当前目录下共生成了 8 个文件。

6.1.5 主机配置

  1. 复制 Server 证书

    /etc/docker 目录下创建 certs.d/<域名>目录。docker 默认会到该目录中查看证书文件。

    将服务器的证书及私钥复制到该目录。

  2. 复制 CA 证书

    docker 默认会查看/etc/pki/tls/certs/ca-bundle.crt 证书中心的证书。所以,需要将 CA 证书复制到该目录下,并重命名为 ca-bundle.crt

6.1.6 重启 docker

systemctl restart docker

6.2 启动镜像中心容器

docker run 命令中除了要指定生成的证书与私钥外,还需要将存放证书与私钥的目录设置为数据卷,以方便容器启动时读取。

docker run --name myregistry \
--restart always \
-v /etc/docker/certs.d/xxx.com:/cert \
-v /var/lib/registry:/var/lib/registry \
-v /root/auth:/auth \
-e "REGISTRY_HTTP_TLS_CERTIFICATE=/cert/xxx.com.cert" \
-e "REGISTRY_HTTP_TLS_KEY=/cert/xxx.com.key" \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd.user" \
-dp 5000:5000 \
registry

查看容器状态,是 UP 状态。

6.3 windows浏览器访问

提交 https 请求。

6.4 Docker客户端操作

使用 Docker 客户端访问遵循 HTTPS 协议的 registry 私有镜像中心,与访问遵循 HTTP 协议的没有区别,对于用户来说是没有感知的。

发出 HTTPS 访问请求。

curl -v https://192.168.254.131:5000

当然,为了证明与 Docker 客户端设置/etc/docker/daemon.json 文件无关,可以将该文件中原来加入的内容删除,重启 Docker 后再测试。

可以看到 docker login 提交的是 https 请求,并且登录成功。

7. harbor 私有镜像中心(HTTP)

无论是使用docker-distribution还是 registry 容器,它们搭建的镜像中心都非常的简陋,没有可视化 Web 界面来管理镜像。而 Harbor 镜像中心解决了这个问题。

7.1 Harbor简介

Harbor 是由 VMware 公司中国团队使用 Go 语言开发的一款 Registry server 开源项目,其是在 Docker Registry 的基础之上进行了二次封装。作为一个企业级私有 Registry 服务器,Harbor 提供了更好的性能与安全,同时也提供了一个非常方便、漂亮的 Web 管理界面。

Harbor 的官网为 https://goharbor.io/

Harbor github 上的官网为 https://github.com/goharbor/harbor

7.2 Harbor安装系统要求

Harbor 要安装的主机需要满足硬件与软件上的要求。

7.2.1 硬件要求

7.2.2 软件要求

7.3 安装Harbor

7.3.1 下载安装包

在官网复制 Latest 最新版的离线安装包的下载链接地址,在 Linux 系统中通过 wget 命令下载,将其下载到某目录中。

wget https://github.com/goharbor/harbor/releases/download/v2.8.1/harbor-offline-installer-v2.8.1.tgz

如果出现证书问题,则使用:

wget --no-check-certificate https://github.com/goharbor/harbor/releases/download/v2.8.1/harbor-offline-installer-v2.8.1.tgz

加上–no-check-certificate 参数即可,出现这个原因还是因为之前证书操作安装有问题导致

7.3.2 解压安装包

将下载好的包解压到某目录中。解压后其就是一个独立的目录 harbor

新建:/opt/apps/目录,然后将harbor-offline-installer-v2.8.1.tgz解压到其中

tar -zxvf harbor-offline-installer-v2.8.1.tgz -C /opt/apps/

7.3.3 修改 harbor.yml

复制一份 harbor 解压包中的 harbor.yml.tmpl,并重命名为 harbor.yml

修改 harbor.yml 配置文件。共修改三处:

  • hostname 指定为docker服务主机的 IP
  • 注释掉所有 https 相关配置
  • 记住(或修改)admin 用户的登录密码

另外需要注意一点,harbor 默认的端口号为 80。

7.3.4 运行 prepare

运行 harbor 解压目录中的 prepare 命令。该命令会先拉取 prepare 镜像,然后再生成很多的其后期要用到的配置文件

这里如果证书安装的有问题,会导致无法拉取。

7.3.5 运行 install.sh

运行 harbor 解压目录中的 install.sh 命令,其会自动完成五步的安装过程,并在最终启动很多的容器。这些容器本质上就是通过 docker-compose 进行编排管理的。

7.4 windows浏览器访问

在浏览器地址栏中输入 http://宿主机IP 即可看到如下页面,在其中输入用户名admin,密码为 harbor.yml 中设置的密码,即可登录。

若安装成功,但是无法访问页面,有两种情况:

  1. 看harbor的服务是否没有启动完全:docker ps -a,将harbor有关的服务全部启动

  2. 如果你是使用的htpp来访问的,你应该修改/etc/docker/deamon.json文件,加上如下内容:

    "insecure-registries": ["你的IP:80"]
    

7.5 Harbor的启停

由于 Harbor 是由 10 个容器同时运行完成的,且是通过 docker-compose 完成的容器编排。Harbor 安装完成后会在 harbor 解压目录中生成 docker-compose.yml 文件,所以 Harbor的启停命令,都是由 docker-compose 完成的,且需要在 harbor 解压目录中完成

7.5.1 Harbor停止

#首先要保证在harbor的解压目录中进行
docker-compose stop

7.5.2 Harbor 启动

#首先要保证在harbor的解压目录中进行
docker-compose up -d

7.6 Docker客户端操作

registry 私有镜像中心搭建成功了,Docker 客户端就可以对其进行操作了。

7.6.1 修改 daemon.json 文件

默认情况下,为了保证安全,Docker 客户端都采用的是 https 提交各种请求,例如,登录请求、pull 请求、push 请求等。但私有镜像中心不接受 https 请求。所以需要告诉 Docker客户端该镜像中心地址是安全的,这样 Docker 客户端将会自动采用 http 请求方式。而对Docker 客户端的告知方式是,手工修改 Docker 客户端的/etc/docker/daemon.json 文件。

7.6.2 重启 docker 引擎

配置文件修改了,需要重启 docker 引擎,以加载新的配置。

systemctl restart docker

7.6.3 登录私有镜像中心

docker login 你的docker服务主机IP

7.6.4 复制并重命名镜像

通过 docker tag 命令可以对原有镜像进行复制并重命名。这个重命名的镜像的<repository>中需要采用<domain-name>/<project-name>/<software-name>格式。当然,如果需要区分用户的话,也可以采用<domain-name>/<project-name>/<username>/<software-name>格式。

首先先新建test项目:

复制并重命名镜像:

7.6.5 推送镜像

7.6.6 登出私有镜像中心

docker logout docker主机IP

8. harbor 私有镜像中心(HTTPS)

8.1 申请腾讯云证书

8.1.1 申请条件

若要在腾讯云申请 SSL 证书,需要具备两个条件:

  • 具备腾讯云账号
  • 具有一个自己申请到的域名。不一定非要是腾讯云申请的。

8.1.2 申请免费证书

https://console.cloud.tencent.com/ssl

速度很快,大概1分钟左右可以完成。

8.1.3 下载证书

选择具体服务器相应的证书进行下载。下载完毕后是一个压缩包,打开压缩包,其中存放着两个文件 pem key

  • key 是为用户生成的私钥。
  • pem 是证书文件。对于证书文件,有两种编码格式:pem derpem 是常用于 Linux系统的编码证书,而 der 是常用于 Windows 系统的编码证书。证书文件中包含了使用 CA 公钥加密过的用户信息及用户公钥,它们分别对应文件中的两部分内容。

8.2 安装Harbor

8.2.1 删除文件

harbor 目录中将原来的 common 目录、docker-compose.ymlharbor.yml 文件删除。即恢复到了刚解压后的状态

8.2.2 复制证书文件

将下载的 pem 证书文件与 key 私钥文件存放到 harbor 主机的任意目录中。这里在 harbor 解压目录中新建一个 cert 目录,专门用于存放这两个文件。为了方便,将两个文件分别重命名为了 server.pemprivate.key

8.2.3 修改 harbor.yml

复制一份 harbor 解压包中的 harbor.yml.tmpl,并重命名为 harbor.yml

修改harbor.yml配置文件。共修改三处:

  • hostname 指定为当前docker主机的域名
  • https 相关配置指定 pem key 文件
  • 记住(或修改)admin 用户的登录密码

8.2.4 运行 prepare

本次再执行 prepare 命令,就不会再看到那个有关 HTTPS warning 了。

8.2.5 运行 install.sh

8.3 windows客户端设置

8.3.1 修改 hosts 文件

由于当前 harbor 部署的主机并没有外网 IP,即申请的域名并没有真正分配给该主机,所以只有临时修改一下 windows 系统中的 DNS 文件,C:\Windows\System32\drivers\etc 目录下的 hosts 文件,以形成一种“假的”IP 与域名间的映射。

hosts 文件中增加一行如下内容:

8.3.2 浏览器访问

8.4 Docker客户端设置

8.4.1 修改 daemon.json

修改 Docker 客户端的/etc/docker/daemon.json 文件。在文件中指定 你的证书绑定的域名为安全镜像中心域名。增加如下内容:

8.4.2 重启 docker 引擎

systemctl restart docker

8.4.3 docker 客户端访问

我这里没有访问成功

我猜测原因:

  • 第一次访问失败,可能是我现在开启了https,所以访问必须要https,所以后面我加上443端口,强制说明我要使用https访问

  • 第二次失败,他说我的验证有问题,但是我前面的一些设置都没有问题,并且配置了/etc/host/中设置了IP 域名的映射,还是访问失败,然后我使用ping 我的域名发现收到了数据,但是IP不是我前面设置的IP

    所以我猜测可能是我申请证书的时候,域名验证方式选择了自动,导致它不按照我的/etc/host/文件设置中的来

注意:在申请域名验证方式的时候,我上面选择了自动验证,你可以选择手动验证测试测试

9. Harbor 架构与工作原理

9.1 Harbor架构模块

Harbor 整体架构中的组件非常多,下面简单介绍几个非常重要的模块。

9.1.1 Proxy

反向代理服务器,由 Nginx 充当。负责接收并转发来自客户端的请求,无论请求是直接来自于浏览器的 HTTP 请求,还是来自于 Docker 客户端的命令。根据不同的请求,Proxy 会将其转发至 Core Registry 模块。

9.1.2 Core

Harbor 的核心模块,有两个非常重要的子服务模块:

  • Notification Manager:通过 webhook 实现的消息管理模块。当 registry 中镜像发生改变时,会立即通知到 web 页面,即会在 web 页面中显示更新。
  • API ServerProxy 根据不同的路由规则将请求首先转发到 API Server 的不同接口。但无论哪个处理接口,都强制要求对请求进行权限控制,即都需要请求先根据不同身份从API Server 中的 AUTH 模块中获取到一个有效的 tokenAUTH 模块是通过 token service实现的用户认证。

9.1.3 GC Collector

负责整个系统中的 GC 管理。

9.1.4 Chart Museum

Helm 的仓库。

9.1.5 Notary

数据权限控制器。

9.1.6 Log Collector

负责Harbor中其他模块的日志汇总。

9.1.7 Job Service

负责镜像复制。在高可用Harbor集群中,通过Job Service可以将本地镜像同步到远程 Harbor实例上。

9.1.8 Distribution

镜像中心,由 registry 镜像充当,负责存储 Docker 镜像,及处理 docker push/pull 请求。

9.1.9 k-v storag

主要是为Job Service提供缓存服务的,将 Job 元数据临时性存放在其中。默认由 Redis充当。所以,Redis 在高可用 Harbor 集群中的作用很大。

9.1.10 Local/Remote Storage

可以将工程元数据、用户数据、角色数据、同步策略以及镜像元数据等存放在本地或远程服务器中的内存块、文件或持久化对象中。不过,一般会使用SQL Database

9.1.11 SQL Database

用于存放工程元数据、用户数据、角色数据、同步策略以及镜像元数据等。默认采用 PostgreSQL数据库。

9.1.12 Harbor架构图及工作原理

有关Harbor的系统架构描述,HarborGitHub的官网中如下地址有直接的描述及架构图https://github.com/goharbor/harbor/wiki/Architecture-Overview-of-Harbor。架构图分解的非常细致。

9.2 Docker命令执行流程

9.2.1 关于公钥与私钥

Harbor搭建完毕后,token service中就会保存该harbor的私钥,registry中保存该harbor的公钥。

使用私钥加密称为数字签名,使用公钥解密称为签名验证。

使用公钥加密称为加密,使用私钥解密成为解密。

9.2.2 docker login命令

docker login命令执行过程

9.2.3 docker push命令

docker pull命令执行过程


文章作者: 念心卓
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 念心卓 !
  目录