镜像中心
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
的用户名。
先创建一个目录:
/root/hdw
在hdw目录中,创建hello.c文件;文件内容如下
#include<stdio.h> int main(){ printf("hello docker hub world\n"); return 0; }
编译hello.c文件
gcc --static -o hello hello.c
运行
编写Dockerfile文件
FROM scratch ADD hello / CMD ["/hello"]
构建镜像
接下来就可以把你的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)
然后选择服务:
实例选择好之后,需要在这下面设置初始密码:
这个密码要记住,后面测试使用腾讯云输入的密码就是这个,如果忘记了密码,这里更多选项可以选择重置密码
这里我选择的是带有个人版本的广州的实例。
命名空间建立以后,选择新建镜像仓库。
接下来就可以进行测试了
2.2 Docker发布镜像到腾讯云
登陆
docker login ccr.ccs.tencentyun.com --username=你的ID
向 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. 私有镜像中心基础知识
3.1 HTTP/HTTPS协议
3.1.1 协议
HTTP
与 HTTPS
协议都是客户端浏览器和服务器间的一种约定,约定如何将服务器中的信息下载到本地,并通过浏览器显示出来。
不同的是,HTTP
协议是一种明文传输协议,其对传输的数据不提供任何加密措施。而HTTPS
协议则是通过 SSL/TLS
为数据加密,以保障数据的安全性。
通常情况下,HTTP
会直接与运输层的 TCP
进行通信,默认使用 80 端口号。但在使用SSL/TLS
协议的 HTTPS
后,就演变成了直接与运输层的 SSL/TLS
进行通信,再由 SSL/TLS
与 TCP
进行通信。即 HTTPS
是间接与 TCP
进行通信的。HTTPS
默认使用 443 端口号
3.1.2 SSL/TLS
SSL
,Secure Sockets Layer
,安全套接字协议
TLS
,Transport 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 通信原理
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 stop
或docker 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
的,这肯定是不安全的。所以,这里在启动镜像中心之前,先创建一个用于保存用户名与密码的文件。这里要使用Apache
的 htpasswd
命令创建用户名与密码。
在任何目录中 mkdir
一个目录 auth
,专门用于存放用户信息。本例选择在/root
目录下创建 auth
目录。然后再将字符串 zhangsan
与 111
分别指定为用户名与密码,并写入到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
创建 CA 的私钥
首先要创建证书中心的私钥。
openssl genrsa -out ca.key 4096
openssl
: 是OpenSSL
工具的命令行接口。genrsa
: 是OpenSSL
命令的子命令,用于生成RSA
密钥对。-out ca.key
: 指定生成的私钥文件的输出路径和文件名,这里是ca.key
。私钥文件通常使用.key
或.pem
后缀。4096
: 指定生成的RSA
密钥的位数,这里是 4096 位。较高的位数提供更高的安全性,但也会增加生成时间和密钥操作的计算量。
此时在当前目录下就生成了
ca.key
文件。可以查看生成私钥的具体内容。创建 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 创建申请者证书
进入到 cert 目录
openssl genrsa -out xxx.com.key 4096
生成请求文件
要生成正式的数字证书文件之前,需要先生成一个包含申请者自身个人信息的请求文件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
文件内容。
生成 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
文件生成申请者证书
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
,只不过是加过密的。重命名证书名
将 crt
文件重命名为 cert
。因为默认情况下,docker
将.crt
文件识别为 CA
证书,将.cert
识别为用户生成的证书。当然,这个重命名也是通过 openssl
命令完成的。
openssl x509 -inform PEM -in xxx.com.crt -out xxx.com.cert
至此在当前目录下共生成了 8 个文件。
6.1.5 主机配置
复制 Server 证书
在
/etc/docker
目录下创建certs.d/<域名>
目录。docker
默认会到该目录中查看证书文件。将服务器的证书及私钥复制到该目录。
复制 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
中设置的密码,即可登录。
若安装成功,但是无法访问页面,有两种情况:
看harbor的服务是否没有启动完全:
docker ps -a
,将harbor有关的服务全部启动如果你是使用的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
与der
。pem
是常用于Linux
系统的编码证书,而der
是常用于Windows
系统的编码证书。证书文件中包含了使用CA
公钥加密过的用户信息及用户公钥,它们分别对应文件中的两部分内容。
8.2 安装Harbor
8.2.1 删除文件
在 harbor
目录中将原来的 common
目录、docker-compose.yml
及 harbor.yml
文件删除。即恢复到了刚解压后的状态。
8.2.2 复制证书文件
将下载的 pem
证书文件与 key
私钥文件存放到 harbor
主机的任意目录中。这里在 harbor
解压目录中新建一个 cert
目录,专门用于存放这两个文件。为了方便,将两个文件分别重命名为了 server.pem
与 private.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 Server
:Proxy
根据不同的路由规则将请求首先转发到API Server
的不同接口。但无论哪个处理接口,都强制要求对请求进行权限控制,即都需要请求先根据不同身份从API Server
中的AUTH
模块中获取到一个有效的token
。AUTH
模块是通过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
的系统架构描述,Harbor
在GitHub
的官网中如下地址有直接的描述及架构图https://github.com/goharbor/harbor/wiki/Architecture-Overview-of-Harbor。架构图分解的非常细致。
9.2 Docker命令执行流程
9.2.1 关于公钥与私钥
Harbor
搭建完毕后,token service
中就会保存该harbor
的私钥,registry
中保存该harbor
的公钥。
使用私钥加密称为数字签名,使用公钥解密称为签名验证。
使用公钥加密称为加密,使用私钥解密成为解密。