Docker 私有仓库

Docker 私有仓库

前言

a. 本文主要为 Docker的视频教程 笔记。
b. 环境为 CentOS 7.0 云服务器
c. 上一篇:Docker 容器间的单向连接

1. 安装与启动

Docker 的仓库软件也被打包在了镜像中,可以使用 docker pull registry 命令获取创建 Docker 仓库的软件 registry

启动命令:

docker run -d -p 5000:5000 --restart=always --name=registry -v /opt/myregistry:/var/lib/registry registry

registry 中存储的路径为 /var/lib/registry,映射到本地的 /opt/myregistry

2. 向私有仓库上传镜像

提前基于 centos:7 做好一个容器,里面有 httpd 和一个自定义的主页,id 为 ff88077f841d,起的名称为 centos_httpd_customindex 。

(1)为镜像打标签

命令为:

docker tag <IMAGE_ID> <ADDRESS_AND_PORT>/<CUSTOM_NAME>:<VERSION>

如:

[root@VM_0_2_centos ~]# docker tag ff88077f841d 127.0.0.1:5000/httpd:v1

(2)上传:

命令为:

docker push <IMAGE_TAG>

如:

[root@VM_0_2_centos ~]# docker push 127.0.0.1:5000/httpd:v1

TIPS: Docker 私有镜像前面有用户名的,如 abc/centos:7, 而 Docker 官方镜像前面没有域名;类似的,Docker 私有仓库前面有域名或 ip 地址,而 Docker 的官方仓库则没有。这些私有仓库镜像的前面的地址就是作为上传地址来使用的

如果不打标签直接上传,则意味上传到 Docker 的官方仓库中,结果为

[root@VM_0_2_centos ~]# docker push centos_httpd_customindex
The push refers to repository [docker.io/library/centos_httpd_customindex]
d5b7ae674584: Preparing
c88ae10680b3: Preparing
16311dc4d3e8: Preparing
ad136decc5d0: Preparing
77b174a6a187: Preparing
denied: requested access to the resource is denied

(3)意料外的情况

在视频教程中,会提示无法使用https访问,此时修改 /etc/docker/daemon.json ,加入私有仓库的ip地址和端口号

{
	"insecure-registries":["<PRIVATE_REGISTRY_ADDRESS_AND_PORT>"]
}

并使用 systemctl restart docker 重启docker服务,但在本地实验时并未出现这种情况。

(4)多种方法查看上传

A. 从文件系统查看

由于映射了目录,因此可以查看到已经上传了的镜像(此处的 v2 的含义是 registry 软件的版本,应该是区别于最开始的 registry 软件版本)

[root@VM_0_2_centos ~]# ls /opt/myregistry/docker/registry/v2/repositories/httpd/_manifests/tags/
v1

由于该镜像是基于 centos:7 做的,如果此时再上传 centos:7 的镜像,由于镜像是分层的,则实际并不会上传,如:

[root@VM_0_2_centos ~]# docker tag centos:7 127.0.0.1:5000/centos:v1
[root@VM_0_2_centos ~]# docker push 127.0.0.1:5000/centos:v1
The push refers to repository [127.0.0.1:5000/centos]
77b174a6a187: Mounted from httpd
v1: digest: sha256:285bc3161133ec01d8ca8680cd746eecbfdbc1faa6313bd863151c4b26d7e5a5 size: 529

可以看到镜像已经通过之前的 httpd 镜像层取得了。

B. 使用 registry 提供的接口查看

使用 http 协议访问(在浏览器中或使用 Postman ) 仓库地址加 /v2/_catalog

如:

[root@VM_0_2_centos ~]# curl localhost:5000/v2/_catalog

查看具体某个镜像有哪些版本,可以访问 仓库地址加/v2/镜像名/tags/list

如:

[root@VM_0_2_centos ~]# curl localhost:5000/v2/centos/tags/list

可以看到之前上传的 centos 有 v1 的版本

3. 为私有仓库加入basic认证

(1)安装密钥工具及生成密钥

安装 apache 的 http 密钥生成工具:

yum install httpd-tools -y

使用 htpasswd 生成密钥

htpasswd -Bbn <USER_NAME> <PASSWORD> >> <PATH_TO_FILE>

其中 htpasswd 的 -B 表示使用某种安全的加密(原文为:“ -B Force bcrypt aencryption of the password (very secure)”, 翻译软件似乎也不能很好地翻译);-b 表示在命令行中输入密码即可,而不是使用交互;-n 表示直接显示在标准输出中(在本例利用 “>>” 从标准输出写入文件);

如:

[root@VM_0_2_centos ~]# mkdir /opt/registry-var/auth -p
[root@VM_0_2_centos ~]# htpasswd -Bbn test 123456 >> /opt/registry-var/auth/htpasswd
[root@VM_0_2_centos ~]# cat /opt/registry-var/auth/htpasswd
test:$2y$05$OB9RRrL2nZTjH5KGYsrqsO4yDE2JIu55URCLP8tvYAD5TnfYWRbw6

(2)启动镜像及效果

删除原有镜像后,使用下面的命令重新启动镜像:

docker run -d -p 5000:5000 --restart=always \
	-v /opt/registry-var/auth/:/auth/ \
	-v /opt/myregistry/:/var/lib/registry \
	-e "REGISTRY_AUTH=htpasswd" \
	-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
	-e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \
	registry

此时再直接使用 http 访问时就会显示 UNAUTHORIZED,如:

[root@VM_0_2_centos ~]# curl localhost:5000/v2/centos/tags/list

应该使用 curl 的命令的参数,发送时加入用户名和密码等验证信息

curl -u '<USER_NAME>:<PASSWORD>' <URL>
或
curl -u '<USER_NAME>' <URL>	# 需要交互输入密码

如:

[root@VM_0_2_centos ~]# curl -u 'test:123456' localhost:5000/v2/centos/tags/list

[root@VM_0_2_centos ~]# curl -u 'test' localhost:5000/v2/centos/tags/list
Enter host password for user 'test':

直接上传镜像和拉取镜像也需要先登陆,如:

[root@VM_0_2_centos ~]# docker push 127.0.0.1:5000/httpd:v2
The push refers to repository [127.0.0.1:5000/httpd]
d5b7ae674584: Preparing
c88ae10680b3: Preparing
16311dc4d3e8: Preparing
ad136decc5d0: Preparing
77b174a6a187: Preparing
no basic auth credentials

使用 docker login 登陆:

[root@VM_0_2_centos ~]# docker login 127.0.0.1:5000
Username: test
Password:
Login Succeeded

再次上传:

[root@VM_0_2_centos ~]# docker push 127.0.0.1:5000/httpd:v2
The push refers to repository [127.0.0.1:5000/httpd]
d5b7ae674584: Layer already exists c88ae10680b3: Layer already exists
16311dc4d3e8: Layer already exists
ad136decc5d0: Layer already exists
77b174a6a187: Layer already exists
v2: digest: sha256:2c8b4238f32e7ad4e670f7bc14619ad670bb0dd472b64f761fbbca24ae53d506 size: 1363

4. 删除私有仓库的镜像

视频教程里的方法时直接进入文件系统删除标签,之后 registry 的 garbage-collect 命令让系统自动判断和删除镜像。在搜索后,发现使用 http 请求访问 api 删除标签的方式比较优雅,但同样也需要利用到容器的 garbage-collect。

先查看现在的镜像情况:

[root@VM_0_2_centos ~]# curl -u 'test:123456' localhost:5000/v2/centos/tags/list

可以看到 centos 的镜像有 v1、v2 两个版本。进入 docker registry 容器,查看占用空间情况:

[root@VM_0_2_centos ~]# docker exec -it 28ca1493ba01 /bin/sh

/ # du -smh /var/lib/registry/docker/registry/
623.9M /var/lib/registry/docker/registry/

TIPS: du 的 -s 表示只显示作为参数的目录的总体情况(而不显示子目录的情况),-h 表示以人类可读的方式(以 KB、MB 等单位显示),-m 表示单位是 MB

(1)使用 api 查看容器 id

命令为:

curl -u '<USER_NAME>:<PASSWORD>' \
	--header "Accept: application/vnd.docker.distribution.manifest.v2+json" \
	-I <ADDRESS_AND_PORT>/v2/<IMAGE_NAME>/manifests/<VERSION>

-I 表示只显示头部信息

注意,名为 Accept 的头一定要加上,否则返回值都会不同,接下来的步骤无法继续操作

如:

[root@VM_0_2_centos ~]# curl -u 'test:123456' --header "Accept: application/vnd.docker.distribution.manifest.v2+json" -I localhost:5000/v2/centos/manifests/v2
HTTP/1.1 200 OK
Content-Length: 742
Content-Type: application/vnd.docker.distribution.manifest.v2+json
Docker-Content-Digest: sha256:41080ebfb60511cfb6c737b1e83bde6f74acbe51992efab6720e0bdfa856e81d
Docker-Distribution-Api-Version: registry/2.0
Etag: "sha256:41080ebfb60511cfb6c737b1e83bde6f74acbe51992efab6720e0bdfa856e81d"
X-Content-Type-Options: nosniff
Date: Mon, 15 Jun 2020 14:09:47 GMT

取其中的 Etag 的 sha256 值。

(2)使用 api 删除容器标签

命令为:

curl -u '<USER_NAME>:<PASSWORD>' \
	 -I -X DELETE <ADDRESS_AND_PORT>/v2/<IMAGE_NAME>/manifests/sha256:<SHA256_ID>

如:

[root@VM_0_2_centos ~]# curl -u 'test:123456' -I -X DELETE localhost:5000/v2/centos/manifests/sha256:41080ebfb60511cfb6c737b1e83bde6f74acbe51992efab6720e0bdfa856e81d
HTTP/1.1 405 Method Not Allowed
Content-Type: application/json; charset=utf-8
Docker-Distribution-Api-Version: registry/2.0
X-Content-Type-Options: nosniff
Date: Mon, 15 Jun 2020 14:00:31 GMT
Content-Length: 78

此时提示: Method Not Allowed,需要进入容器,修改 registry 的配置,使其可以允许修改

/ # vi /etc/docker/registry/config.yml
/ # cat /etc/docker/registry/config.yml
version: 0.1
log:
  fields:
    service: registry
storage:
  cache:
    blobdescriptor: inmemory
  filesystem:
    rootdirectory: /var/lib/registry
  delete:	#加入此处的配置
    enabled: true
http:
  addr: :5000
  headers:
    X-Content-Type-Options: [nosniff]
health:
  storagedriver:
    enabled: true
    interval: 10s
    threshold: 3

宿主机重启服务后,再次执行:

d[root@VM_0_2_centos ~]# curl -u 'test:123456' -I -X DELETE localhost:5000/v2/centos/manifests/sha256:41080ebfb60511cfb6c737b1e83bde6f74acbe51992efab6720e0bdfa856e81d
HTTP/1.1 202 Accepted
Docker-Distribution-Api-Version: registry/2.0
X-Content-Type-Options: nosniff
Date: Mon, 15 Jun 2020 14:10:49 GMT
Content-Length: 0

返回成功!

(3)进入容器删除实际文件

此时再次查看虽然标签删除了但空间未释放:

[root@VM_0_2_centos ~]# curl -u 'test:123456' localhost:5000/v2/centos/tags/list
{"name":"centos","tags":["v1"]}
[root@VM_0_2_centos ~]# docker exec -it 28ca1493ba01 /bin/sh
/ # du -smh /var/lib/registry/docker/registry/
623.9M /var/lib/registry/docker/registry/

在容器使用 registry 的 garbage-collect 进行垃圾回收,命令为:

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

如:

/ # registry garbage-collect /etc/docker/registry/config.yml
centos
centos: marking manifest sha256:285bc3161133ec01d8ca8680cd746eecbfdbc1faa6313bd863151c4b26d7e5a5
centos: marking blob sha256:5e35e350aded98340bc8fcb0ba392d809c807bc3eb5c618d4a0674d98d88bccd
centos: marking blob sha256:ab5ef0e5819490abe86106fd9f4381123e37a03e80e650be39f7938d30ecb530
3 blobs marked, 4 blobs and 0 manifests eligible for deletion
blob eligible for deletion: sha256:41080ebfb60511cfb6c737b1e83bde6f74acbe51992efab6720e0bdfa856e81d
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/41/41080ebfb60511cfb6c737b1e83bde6f74acbe51992efab6720e0bdfa856e81d go.version=go1.11.2 instance.id=f5f44c4e-5078-4547-9311-150697d0a9d4 service=registry
blob eligible for deletion: sha256:4c21c94fbbc522156e0fe9534360ac6ce4dd0ff5b2a41fbf9671d1568e0c7a62
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/4c/4c21c94fbbc522156e0fe9534360ac6ce4dd0ff5b2a41fbf9671d1568e0c7a62 go.version=go1.11.2 instance.id=f5f44c4e-5078-4547-9311-150697d0a9d4 service=registry
blob eligible for deletion: sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/a3/a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4 go.version=go1.11.2 instance.id=f5f44c4e-5078-4547-9311-150697d0a9d4 service=registry
blob eligible for deletion: sha256:e60b4e126932ec4b65ce79c5b06198f0bee0eccfefff86e33ab9b5aad6292372
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/e6/e60b4e126932ec4b65ce79c5b06198f0bee0eccfefff86e33ab9b5aad6292372 go.version=go1.11.2 instance.id=f5f44c4e-5078-4547-9311-150697d0a9d4 service=registry

再次查看空间发现占用确实减少了:

/ # du -smh /var/lib/registry/docker/registry/
72.6M /var/lib/registry/docker/registry/

PS:视频教程中的做法为进入容器中删除镜像的标签: rm -rf /var/lib/registry/docker/registry/v2/repositories/centos,之后再进入容器执行垃圾回收。

参考

htpasswd 的使用:

https://www.jianshu.com/p/f4120aa561cc

删除本地仓库中的 Docker 镜像:

https://blog.csdn.net/weixin_43905458/article/details/104947884

posted @ 2020-06-21 16:27  battor  阅读(915)  评论(0编辑  收藏  举报