参考文章:[Docker 技术入门与实战 第3板]
本章将具体讲解 Registry 的使用技巧,并通过案例来展示如何搭建一个功能完善的私有镜像仓库。在搭建完本地的私有仓库服务后,来剖析 Registry 的配置参数,最后会通过编写脚本来实现对镜像的快速批量化管理。
安装 Docker Registry
Docker Registry 工具目前最新为 2.0 系列版本,这一版本和一些类库和工具一起被打包为负责容器内容分发的工具集:Docker Distribution。目前其核心的功能组件仍未负责镜像仓库的管理。
新版本的 Registry 基于 Golang 进行了重构,提供更好的性能和扩扎性,并且支持 Docker 1.6+ 的 API,非常适合用来构建私有的镜像注册服务器。官方仓库中也提供了 Registry 的镜像,因此用户可以通过容器运行和源码安装两种方式来使用 Registry。
基于容器安装运行
基于容器的运行方式十分简单,只需要一条命令:
1 | docker run -d -p 5000:5000 --restart=always --name registry registry:2 |
启动服务后,服务监听本地的 5000 端口,可以通过访问 http://localhost:5000/v2/
测试启动成功。
Registry 比较关键的参数时配置文件和仓库存储路径。默认的配置文件为 /etc/docker/registry/config,yml
,因此,通过如下命令,可以指定使用本地主机上的配置文件(如 /home/user/registry-conf
):
1 | docker run -d -p 5000:5000 \ |
默认的存储位置为 /var/lib/registry
,也可以通过 -v
参数来映射本地的路径到容器内。
1 | docker run -d -p 5000:5000 \ |
本地安装运行
有时候需要本地运行仓库服务,可以通过源码的方式进行安装。
首先安装 Golang 环境支持,以 CentOS 为例,可以执行如下命令:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# 下载 Go 安装包
wget https://golang.google.cn/dl/go1.15.6.linux-amd64.tar.gz
# 解压安装包
sudo tar -zxf go1.15.6.linux-amd64.tar.gz -C /usr/local/
# 添加环境变量
cat >/etc/profile.d/go.sh<<EOF
#!/bin/bash
GO_HOME=/usr/local/go
PATH=$PATH:$GO_HOME/bin
EOF
# 测试
source /etc/profile.d/go.sh
go version
go version go1.15.6 linux/amd64在 GO 家目录下,创建
src/github.com/docker/
目录,并拉取 registry 源码1
2
3
4
5
6
7# 创建目录
sudo mkdir -p /usr/local/go/src/github.com/docker
# 拉取代码
cd /usr/local/go/src/github.com/docker/
git clone https://github.com/docker/distribution.git
cd distribution将自带的模板复制到
/etc/docker/registry
目录下,创建存储目录/var/lib/registry
1
2
3sudo mkdir /etc/docker/registry
sudo cp cmd/registry/config-dev.yml /etc/docker/registry/config.yml
sudo mkdir /var/lib/registry执行安装操作
1
2
3
4
5
6cd /usr/local/go/src/github.com/docker/distribution
make PREFIX=/usr/local/go clean binaries
# 编译安装时可能会报 代理错误,此时需要设置 go 环境使用 GO111MODULE
go env -w GO111MODULE=on
# 使用阿里云代理
go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/,direct编译安装后,可执行的二进制文件在
distribution/bin
下面,添加环境变量1
2
3
4
5
6sudo vim /etc/profile.d/registry.sh
#!/bin/bash
REGISTRY_HOME=/usr/local/go/src/github.com/docker/distribution
PATH=$PATH:$REGISTRY_HOME/bin可以通过下面的命令来启动 registry
1
registry serve /etc/docker/registry/config.yml
此时使用
curl
访问本地的 5000 端口,看到返回信息为200 OK
,则说明运行成功1
2
3
4
5
6
7
8$ curl -i http://127.0.0.1:5000/v2/
HTTP/1.1 200 OK
Content-Length: 2
Content-Type: application/json
Docker-Distribution-Api-Version: registry/2.0
X-Content-Type-Options: nosniff
Date: Tue, 22 Dec 2020 02:00:27 GMT
{}
配置
创建主机目录
创建
/data/docker/registry
目录,里面存放的是主机本地文件,和容器目录进行映射1
mkdir -p /data/docker/registry
创建 registry 容器需要的三个目录
1
2cd /data/docker/registry
mkdir -p auth certs data
创建签名证书
生成证书要使用域名,我这里定为:
registry.59izt.com
,(不用域名,直接用IP的话,要修改 openssl 配置文件,建议用域名)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22# openssl req -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key -x509 -days 365 -out certs/domain.crt -extensions v3_req
openssl req -newkey rsa:4096 -nodes -sha256 -keyout /data/docker/registry/certs/domain.key -x509 -days 365 -out /data/docker/registry/certs/domain.crt
..................................................++
...................................................................................................................................................................................................................................++
writing new private key to '/data/docker/registry/certs/domain.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]:CN
State or Province Name (full name) []:ShangHai
Locality Name (eg, city) [Default City]:PuDongXinQu
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:registry.59izt.com
Email Address []:注意上面的 Common Name 一定要填写域名地址,或者 IP 地址;
导出证书到 TLS(可选)
1
cat certs/domain.crt >>/etc/pki/tls/certs/ca-bundle.crt
配置 SSL 使用 IP地址取代 DNS,修改 openssl 配置文件(如果使用域名的话可以不用做这一步)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15# 编辑配置文件
vim /etc/pki/tls/openssl.cnf
# 在 req 配置项中添加扩展属性 req_extensions
[ req ]
req_extensions = v3_req # The extensions to add a certificate request
# 在 v3_req 配置项中添加属性 subjectAltNAME
[ v3_req ]
subjectAltName = @alternative_names
# 添加一个 alternative_names 配置项
[ alternative_names ]
IP.1 = 111.111.111.111
创建密码文件
运行 registry 2.6.2
镜像,使用 htpasswd
生成密码文件
1 | docker run --entrypoint htpasswd registry:2.6.2 -Bbn wanwu test123 > auth/htpasswd |
注:注意上面的 registry 版本,使用默认的 registry:2 会提示缺少
exec: "htpasswd": executable file not found in $PATH: unknown.
生成密码使用的 htpasswd 命令需要在镜像中安装httpd-tools
软件,
运行
重启 registry 所在主机的 docker 服务
1 | systemctl restart docker |
启动 registry 容器
1 | docker run -d --name registry \ |
参数说明:
-d
,后台运行容器-p 5000:5000
,映射容器 5000 端口至宿主机 5000 端口。--restart=always
,设置重新启动策略,在docker重新启动时自动重新启动容器 registry。--name registry
,给容器命名。-v /data/docker/registry/data:/var/lib/registry
,把 docker容器中/var/lib/registry
目录的数据加载到宿主机的/data/docker/registry/data
目录,宿主机的目录如果不存在会自动创建。目的是为了防止docker私有仓库这个容器被删除时,仓库里的镜像也会被删除。宿主机查看到的私有仓库镜像就在这个目录中。-e REGISTRY_STORAGE_DELETE_ENABLED
,设置是否允许删除仓库存储的镜像。-e REGISTRY_HTTP_ADDR=0.0.0.0:5000
,设置镜像仓库地址。-v /data/docker/registry/certs:/certs
, 挂载目录/data/docker/registry/certs
至容器的目录/certs
。-e REGISTRY_HTTP_SECRET
,设置证书的位置。-e REGISTRY_HTTP_TLS_KEY
,设置私钥的位置。-v /data/docker/registry/auth:/auth
,挂载本机的/data/docker/registry/auth
目录至容器/auth
目录。-e REGISTRY_AUTH
,设置环境变量告诉容器密码文件名。-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm"
,设置身份验证的领域。-e REGISTRY_AUTH_HTPASSWD_PATH
,设置环境变量告诉容器存放账户、密码的位置。
查看启动日志
1 | time="2020-12-24T04:02:45.206990427Z" level=info msg="redis not configured" go.version=go1.11.2 instance.id=33307efe-7571-41d1-8eb9-30bc32313e56 service=registry version=v2.7.1 |
显示正在监听 5000 端口
测试
检查 SSL 是否配置成功
1 | curl -i 192.168.200.25:5000 |
测试登录
客户端创建证书存放目录,以及复制服务器的
certs
证书到新建的证书存放目录下1
2sudo mkdir -p /etc/docker/certs.d/registry.59izt.com
sudo scp wanwu@192.168.200.25:/data/docker/registry/certs/* /etc/docker/certs.d/registry.59izt.com/测试登录 registry 服务器
1
2
3
4
5
6
7
8docker login registry.59izt.com:5000
Username: wanwu
Password:
WARNING! Your password will be stored unencrypted in /home/wanwu/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded如上所示,登录成功。如梭登录时提示
Error response from daemon: Get https://registry.59izt.com:5000/v2/: http: server gave HTTP response to HTTPS client
,这是因为 Docker自从1.3.X之后docker registry交互默认使用的是HTTPS,但是搭建私有镜像默认使用的是HTTP服务,所以与私有镜像交时出现以上错误。解决方案如下编写 /etc/docker/daemon.json 文件,添加以下内容,然后重启 docker 服务:1
2
3
4
5{
...
"insecure-registries":["registry.59izt.com:5000", "192.168.200.25:5000"]
...
}测试上传镜像
1
2
3
4
5
6
7docker tag hello-world:latest registry.59izt.com:5000/client-hello-world
docker push registry.59izt.com:5000/client-hello-world
Using default tag: latest
The push refers to repository [registry.59izt.com:5000/client-hello-world]
9c27e219663c: Pushed
latest: digest: sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 size: 525测试下载镜像
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21# 删除本地镜像 hello-world 以及 registry.59izt.com:5000/client-hello-world
docker rmi hello-world
docker rmi registry.59izt.com:5000/client-hello-world
# 从 热感istry9izt.com 拉取镜像
docker pull registry.59izt.com:5000/client-hello-world
Using default tag: latest
latest: Pulling from client-hello-world
0e03bdcc26d7: Pull complete
Digest: sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042
Status: Downloaded newer image for registry.59izt.com:5000/client-hello-world:latest
registry.59izt.com:5000/client-hello-world:latest
# 给镜像打标签
docker tag registry.59izt.com:5000/client-hello-world hello-world:latest
# 查看镜像列表
docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 11 months ago 13.3kB
registry.59izt.com:5000/client-hello-world latest bf756fb1ae65 11 months ago 13.3kB
使用 web 界面浏览删除有仓库镜像
使用以下的命令启动一个新容器,并链接到 registry
容器
1 | # 启动新容器 |
参数说明:
-d
后台运行容器。-p 8080:8080
,映射容器8080端口至宿主机8080端口。--restart always
,设置重新启动策略,在docker重新启动时自动重新启动容器 registry_web。--name registry
给容器命名。--link
,设置连接的仓库。-e REGISTRY_URL
,设置仓库URL,如果使用证书创建容器,仓库URL以 https 开头。-e REGISTRY_NAME
,设置仓库主机。-e REGISTRY_READONLY
,设置web界面是否显示读写、删除按钮。-e REGISTRY_BASIC_AUTH
,设置web界面基本身份验证信息。-e REGISTRY_TRUST_ANY_SSL
,设置信任任何SSL的连接。