docker使用registry搭建本地镜像仓库实例详解

一.系统环境

服务器版本 docker软件版本 CPU架构 CentOS Linux release 7.4.1708 (Core) Docker version 20.10.12 x86_64

二.前言

在使用Docker拉取镜像时,Docker首先默认从Docker Hub官方下载镜像,很多时候我们的镜像都是使用Dockerfile自定义私有镜像,不对外公开,而且为了安全起见,docker可能在内网环境下运行,所以我们有必要搭建一套docker本地私有镜像仓库,以供整个内网集群环境使用。

搭建镜像仓库主流的有两种方法,一种是使用docker官方提供的registry镜像搭建仓库,简单快捷,但是功能有限;

另一种是使用harbor搭建本地镜像仓库,harbor功能更强,使用范围更广,这里介绍使用registry搭建本地镜像仓库。

使用harbor搭建本地镜像仓库请查看http://www.tuohang.net/article/240664.html

三.使用registry搭建私有镜像仓库

3.1 环境介绍

架构:k8smaster作为私有仓库,k8sworker1作为docker客户端

服务器 操作系统版本 CPU架构 进程 功能描述 k8smaster/192.168.110.137 CentOS Linux release 7.4.1708 (Core) x86_64 registry registry镜像仓库 k8sworker1/192.168.110.138 CentOS Linux release 7.4.1708 (Core) x86_64 docker docker客户端

3.2 k8smaster节点配置镜像仓库

拉取registry镜像

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@k8smaster ~]# docker pull hub.c.163.com/library/registry:latest
latest: Pulling from library/registry
25728a036091: Pull complete
0da5d1919042: Pull complete
e27a85fd6357: Pull complete
d9253dc430fe: Pull complete
916886b856db: Pull complete
Digest: sha256:fce8e7e1569d2f9193f75e9b42efb07a7557fc1e9d2c7154b23da591e324f3d1
Status: Downloaded newer image for hub.c.163.com/library/registry:latest
hub.c.163.com/library/registry:latest
#registry镜像已经拉取下来
[root@k8smaster ~]# docker images
REPOSITORY                                                        TAG        IMAGE ID       CREATED          SIZE
hub.c.163.com/library/registry                                    latest     751f286bc25e   4 years ago      33.2MB

查看registry镜像的端口:EXPOSE 5000/tcp 数据卷:VOLUME [/var/lib/registry]

?
1
2
3
4
5
6
7
8
9
10
11
12
[root@k8smaster ~]# docker history hub.c.163.com/library/registry:latest
IMAGE          CREATED       CREATED BY                                      SIZE      COMMENT
751f286bc25e   4 years ago   /bin/sh -c #(nop)  CMD [“/etc/docker/registr…   0B       
<missing>      4 years ago   /bin/sh -c #(nop)  ENTRYPOINT [“/entrypoint.…   0B       
<missing>      4 years ago   /bin/sh -c #(nop) COPY file:7b57f7ab1a8cf85c…   155B     
<missing>      4 years ago   /bin/sh -c #(nop)  EXPOSE 5000/tcp              0B       
<missing>      4 years ago   /bin/sh -c #(nop)  VOLUME [/var/lib/registry]   0B       
<missing>      4 years ago   /bin/sh -c #(nop) COPY file:6c4758d509045dc4…   295B     
<missing>      4 years ago   /bin/sh -c #(nop) COPY file:b99d4fe47ad1addf…   22.8MB   
<missing>      4 years ago   /bin/sh -c set -ex     && apk add –no-cache…   5.61MB   
<missing>      4 years ago   /bin/sh -c #(nop)  CMD [“/bin/sh”]              0B       
<missing>      4 years ago   /bin/sh -c #(nop) ADD file:89e72bfc19e81624b…   4.81MB   

创建registry容器,registry镜像生成容器作为私有仓库

-p 5000:5000做端口映射,物理机端口5000:容器端口5000

-v /docker/var/lib/registry:/var/lib/registry数据卷挂载,

物理机目录/docker/var/lib/registry:容器目录/var/lib/registry

?
1
2
3
4
5
[root@k8smaster ~]# docker run -dit –restart=always –name=docker-registry -p 5000:5000 -v /docker/var/lib/registry:/var/lib/registry hub.c.163.com/library/registry:latest
3f8378272356bece1d690f16ad925bbd25a9ec12840d0612df2c45f84c27b3f5
[root@k8smaster ~]# docker ps
CONTAINER ID   IMAGE                                                 COMMAND                  CREATED         STATUS         PORTS                                       NAMES
3f8378272356   hub.c.163.com/library/registry:latest                 “/entrypoint.sh /etc…”   4 seconds ago   Up 2 seconds   0.0.0.0:5000-&gt;5000/tcp, :::5000-&gt;5000/tcp   docker-registry

此时仓库下还没有任何文件

?
1
[root@k8smaster ~]# ls /docker/var/lib/registry

3.3 k8sworker1节点配置从私有仓库上传和拉取镜像

3.3.1 上传镜像到私有仓库

现在在k8sworker1配置docker客户端

查看现有的镜像,如果没有镜像,直接docker pull即可

?
1
2
3
4
5
[root@k8sworker1 ~]# docker images
REPOSITORY                                                TAG       IMAGE ID       CREATED         SIZE
hub.c.163.com/library/wordpress                           latest    dccaeccfba36   4 years ago     406MB
hub.c.163.com/library/tomcat                              latest    72d2be374029   4 years ago     292MB
hub.c.163.com/library/mysql                               latest    9e64176cd8a2   4 years ago     407MB

docker tag对镜像进行重命名,命名格式为:私有仓库ip:端口/分类/镜像:镜像版本

?
1
2
3
[root@k8sworker1 ~]# docker tag hub.c.163.com/library/wordpress 192.168.110.137:5000/boke/wordpress:latest
[root@k8sworker1 ~]# docker tag hub.c.163.com/library/tomcat 192.168.110.137:5000/web/tomcat:v1
[root@k8sworker1 ~]# docker tag hub.c.163.com/library/mysql 192.168.110.137:5000/db/mysql:5.7

把我们命名好的镜像推送到k8smatser的仓库里,但是报错了,报错客户端的连接为HTTPS,但是服务器端返回的是http

?
1
2
3
[root@k8sworker1 ~]# docker push 192.168.110.137:5000/boke/wordpress:latest
The push refers to repository [192.168.110.137:5000/boke/wordpress]
Get https://192.168.110.137:5000/v2/: http: server gave HTTP response to HTTPS client

解决方式有两种:第一种修改/usr/lib/systemd/system/docker.service文件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
[root@k8sworker1 ~]# systemctl status docker
● docker.service – Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: active (running) since 二 2022-01-04 10:53:14 CST; 7h ago
Docs: https://docs.docker.com
Main PID: 1039 (dockerd)
Memory: 1.2G
CGroup: /system.slice/docker.service
└─1039 /usr/bin/dockerd -H fd:// –containerd=/run/containerd/containerd.sock
#/usr/bin/dockerd有一个参数–insecure-registry用于指定不安全的仓库
[root@k8sworker1 ~]# /usr/bin/dockerd –help | grep insecure
–insecure-registry list                  Enable insecure registry communication
[root@k8sworker1 ~]# vim /usr/lib/systemd/system/docker.service
#修改内容如下:添加了私有仓库地址和端口  –insecure-registry 192.168.110.137:5000
[root@k8sworker1 ~]# cat /usr/lib/systemd/system/docker.service | grep insecure-registry
ExecStart=/usr/bin/dockerd –insecure-registry 192.168.110.137:5000 -H fd:// –containerd=/run/containerd/containerd.sock
#重新加载配置文件并重启docker
[root@k8sworker1 ~]# systemctl daemon-reload ; systemctl restart docker
[root@k8sworker1 ~]# systemctl status docker
● docker.service – Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: active (running) since 二 2022-01-04 17:57:26 CST; 14s ago
Docs: https://docs.docker.com
Main PID: 62817 (dockerd)
Memory: 49.0M
CGroup: /system.slice/docker.service
└─62817 /usr/bin/dockerd –insecure-registry 192.168.110.137:5000 -H fd:// –containerd=/run/containerd/containerd.sock
#此时,推送wordpress镜像到私有仓库成功
[root@k8sworker1 ~]# docker push 192.168.110.137:5000/boke/wordpress:latest
The push refers to repository [192.168.110.137:5000/boke/wordpress]
53e16fa1f104: Pushed
562dd11ed871: Pushed
……
ddd6dcab19ff: Pushed
2c40c66f7667: Pushed
latest: digest: sha256:ca4cf4692b7bebd81f229942c996b1c4e6907d6733e977e93d671a54b8053a22 size: 4078

第二种方式是修改/etc/docker/daemon.json

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#新增”insecure-registries”:[“192.168.110.137:5000”]
[root@k8sworker1 ~]# cat /etc/docker/daemon.json
{
“registry-mirrors”: [“https://frz7i079.mirror.aliyuncs.com”],
“insecure-registries”:[“192.168.110.137:5000”]
}
[root@k8sworker1 ~]# systemctl restart docker
[root@k8sworker1 ~]# cat /etc/docker/daemon.json
{
“registry-mirrors”: [“https://frz7i079.mirror.aliyuncs.com”],
“insecure-registries”:[“192.168.110.137:5000”]
}
#推送tomcat镜像到私有仓库成功
[root@k8sworker1 ~]# docker push 192.168.110.137:5000/web/tomcat:v1
The push refers to repository [192.168.110.137:5000/web/tomcat]
f79699072473: Pushed
……
fe40be59465f: Pushed
cf4ecb492384: Pushed
v1: digest: sha256:6241d7435b5c4e9d54be7d61e834836a71b1934b5403e01eff8768f0e2bcf210 size: 3045
[root@k8sworker1 ~]# docker push 192.168.110.137:5000/db/mysql:5.7
The push refers to repository [192.168.110.137:5000/db/mysql]
8129a85b4056: Pushed
……
295d6a056bfd: Pushed
5.7: digest: sha256:c0806ac73235043de2a6cb4738bb2f6a74f71d9c7aa0f19c8e7530fd6c299e75 size: 2617

查看私有仓库里的镜像

?
1
2
[root@k8sworker1 ~]# curl 192.168.110.137:5000/v2/_catalog
{“repositories”:[“boke/wordpress”,”db/mysql”,”web/tomcat”]}

查看某个镜像的版本

?
1
2
[root@k8sworker1 ~]# curl 192.168.110.137:5000/v2/boke/wordpress/tags/list
{“name”:”boke/wordpress”,”tags”:[“latest”]}

安装jq

?
1
2
3
4
5
6
7
8
[root@k8sworker1 ~]# yum -y install jq
已加载插件:fastestmirror
base                                                                                                         ……
已安装:
jq.x86_64 0:1.6-2.el7                                                                                                                                                                                         
作为依赖被安装:
oniguruma.x86_64 0:6.8.2-1.el7                                                                                                                                                                                
完毕!

使用脚本查看私有仓库里的镜像

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@k8sworker1 ~]# cat list_images_from_registries.sh
#!/bin/bash
file=$(mktemp)
curl -s $1:5000/v2/_catalog | jq | egrep -v \{|\}|\[|] | awk -F\” {print $2} &gt; $file
while read aa ; do
tag=($(curl -s $1:5000/v2/$aa/tags/list | jq | egrep -v \{|\}|\[|]|name | awk -F\” {print $2}))
for i in ${tag[*]} ; do
echo $1:5000/${aa}:$i
done
done &lt; $file
rm -rf $file
[root@k8sworker1 ~]# bash list_images_from_registries.sh 192.168.110.137
192.168.110.137:5000/boke/wordpress:latest
192.168.110.137:5000/db/mysql:5.7
192.168.110.137:5000/web/tomcat:v1

先使用docker rmi 删除刚才修改的本地镜像

?
1
2
[root@k8sworker1 ~]# docker images
REPOSITORY                                                TAG       IMAGE ID       CREATED         SIZE
3.3.2 从私有仓库里拉取镜像

从私有仓库里拉取镜像

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@k8sworker1 ~]# docker pull 192.168.110.137:5000/boke/wordpress:latest
latest: Pulling from boke/wordpress
21f90b3df721: Pull complete
13ce341a48bc: Pull complete
……
500c148f4d2b: Pull complete
Digest: sha256:ca4cf4692b7bebd81f229942c996b1c4e6907d6733e977e93d671a54b8053a22
Status: Downloaded newer image for 192.168.110.137:5000/boke/wordpress:latest
192.168.110.137:5000/boke/wordpress:latest
[root@k8sworker1 ~]# docker pull 192.168.110.137:5000/web/tomcat:v1
v1: Pulling from web/tomcat
a2149b3f2ac2: Pull complete
……
8dbb09972def: Pull complete
Digest: sha256:6241d7435b5c4e9d54be7d61e834836a71b1934b5403e01eff8768f0e2bcf210
Status: Downloaded newer image for 192.168.110.137:5000/web/tomcat:v1
192.168.110.137:5000/web/tomcat:v1
[root@k8sworker1 ~]# docker images
REPOSITORY                                                TAG       IMAGE ID       CREATED         SIZE
192.168.110.137:5000/boke/wordpress                       latest    dccaeccfba36   4 years ago     406MB
192.168.110.137:5000/web/tomcat                           v1        72d2be374029   4 years ago     292MB

从docker客户端上传镜像之后,仓库文件夹里已经存在镜像了

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@k8smaster ~]# ls /docker/var/lib/registry
docker
[root@k8smaster ~]# ls /docker/var/lib/registry/docker/
registry
[root@k8smaster ~]# ls /docker/var/lib/registry/docker/registry/
v2
[root@k8smaster ~]# ls /docker/var/lib/registry/docker/registry/v2/
blobs  repositories
[root@k8smaster ~]# ls /docker/var/lib/registry/docker/registry/v2/repositories/
boke  db  web
[root@k8smaster ~]# ls /docker/var/lib/registry/docker/registry/v2/repositories/boke/
wordpress
[root@k8smaster ~]# ls /docker/var/lib/registry/docker/registry/v2/repositories/boke/wordpress/
_layers  _manifests  _uploads

使用脚本删除私有仓库里的镜像(脚本在附录里)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
#给脚本授予可执行权限
[root@k8smaster ~]# chmod +x delete_docker_registry_image
#设置私有仓库的镜像文件夹
[root@k8smaster ~]# export REGISTRY_DATA_DIR=/docker/var/lib/registry/docker/registry/v2/
#删除私有仓库的wordpress镜像
[root@k8smaster ~]# ./delete_docker_registry_image -i boke/wordpress:latest
INFO     [2022-01-04 19:56:08,375]  Deleting /docker/var/lib/registry/docker/registry/v2/blobs/sha256/46/4676067592f277e1723e4ab4c588603df0b3dea762e22c354f7ada29b391cf10
…….
INFO     [2022-01-04 19:56:08,412]  Deleting /docker/var/lib/registry/docker/registry/v2/repositories/boke/wordpress
#在docker客户端查看发现私有仓库里的wordpress镜像已经被删除了
[root@k8sworker1 ~]# bash list_images_from_registries.sh 192.168.110.137
192.168.110.137:5000/db/mysql:5.7
192.168.110.137:5000/web/tomcat:v1

四.附录:删除私有仓库镜像的Python脚本

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
[root@k8smaster ~]# cat delete_docker_registry_image
#!/usr/bin/env python
“””
Usage:
Shut down your registry service to avoid race conditions and possible data loss
and then run the command with an image repo like this:
delete_docker_registry_image.py –image awesomeimage –dry-run
“””
import argparse
import json
import logging
import os
import sys
import shutil
import glob
logger = logging.getLogger(__name__)
def del_empty_dirs(s_dir, top_level):
“””recursively delete empty directories”””
b_empty = True
for s_target in os.listdir(s_dir):
s_path = os.path.join(s_dir, s_target)
if os.path.isdir(s_path):
if not del_empty_dirs(s_path, False):
b_empty = False
else:
b_empty = False
if b_empty:
logger.debug(“Deleting empty directory %s”, s_dir)
if not top_level:
os.rmdir(s_dir)
return b_empty
def get_layers_from_blob(path):
“””parse json blob and get set of layer digests”””
try:
with open(path, “r”) as blob:
data_raw = blob.read()
data = json.loads(data_raw)
if data[“schemaVersion”] == 1:
result = set([entry[“blobSum”].split(“:”)[1] for entry in data[“fsLayers”]])
else:
result = set([entry[“digest”].split(“:”)[1] for entry in data[“layers”]])
if “config” in data:
result.add(data[“config”][“digest”].split(“:”)[1])
return result
except Exception as error:
logger.critical(“Failed to read layers from blob:%s”, error)
return set()
def get_digest_from_blob(path):
“””parse file and get digest”””
try:
with open(path, “r”) as blob:
return blob.read().split(“:”)[1]
except Exception as error:
logger.critical(“Failed to read digest from blob:%s”, error)
return “”
def get_links(path, _filter=None):
“””recursively walk `path` and parse every link inside”””
result = []
for root, _, files in os.walk(path):
for each in files:
if each == “link”:
filepath = os.path.join(root, each)
if not _filter or _filter in filepath:
result.append(get_digest_from_blob(filepath))
return result
class RegistryCleanerError(Exception):
pass
class RegistryCleaner(object):
“””Clean registry”””
def __init__(self, registry_data_dir, dry_run=False):
self.registry_data_dir = registry_data_dir
if not os.path.isdir(self.registry_data_dir):
raise RegistryCleanerError(“No repositories directory found inside ” \
“REGISTRY_DATA_DIR {0}.”.
format(self.registry_data_dir))
self.dry_run = dry_run
def _delete_layer(self, repo, digest):
“””remove blob directory from filesystem”””
path = os.path.join(self.registry_data_dir, “repositories”, repo, “_layers/sha256”, digest)
self._delete_dir(path)
def _delete_blob(self, digest):
“””remove blob directory from filesystem”””
path = os.path.join(self.registry_data_dir, “blobs/sha256”, digest[0:2], digest)
self._delete_dir(path)
def _blob_path_for_revision(self, digest):
“””where we can find the blob that contains the json describing this digest”””
return os.path.join(self.registry_data_dir, “blobs/sha256”,
digest[0:2], digest, “data”)
def _blob_path_for_revision_is_missing(self, digest):
“””for each revision, there should be a blob describing it”””
return not os.path.isfile(self._blob_path_for_revision(digest))
def _get_layers_from_blob(self, digest):
“””get layers from blob by digest”””
return get_layers_from_blob(self._blob_path_for_revision(digest))
def _delete_dir(self, path):
“””remove directory from filesystem”””
if self.dry_run:
logger.info(“DRY_RUN: would have deleted %s”, path)
else:
logger.info(“Deleting %s”, path)
try:
shutil.rmtree(path)
except Exception as error:
logger.critical(“Failed to delete directory:%s”, error)
def _delete_from_tag_index_for_revision(self, repo, digest):
“””delete revision from tag indexes”””
paths = glob.glob(
os.path.join(self.registry_data_dir, “repositories”, repo,
“_manifests/tags/*/index/sha256”, digest)
)
for path in paths:
self._delete_dir(path)
def _delete_revisions(self, repo, revisions, blobs_to_keep=None):
“””delete revisions from list of directories”””
if blobs_to_keep is None:
blobs_to_keep = []
for revision_dir in revisions:
digests = get_links(revision_dir)
for digest in digests:
self._delete_from_tag_index_for_revision(repo, digest)
if digest not in blobs_to_keep:
self._delete_blob(digest)
self._delete_dir(revision_dir)
def _get_tags(self, repo):
“””get all tags for given repository”””
path = os.path.join(self.registry_data_dir, “repositories”, repo, “_manifests/tags”)
if not os.path.isdir(path):
logger.critical(“No repository %s found in repositories directory %s”,
repo, self.registry_data_dir)
return None
result = []
for each in os.listdir(path):
filepath = os.path.join(path, each)
if os.path.isdir(filepath):
result.append(each)
return result
def _get_repositories(self):
“””get all repository repos”””
result = []
root = os.path.join(self.registry_data_dir, “repositories”)
for each in os.listdir(root):
filepath = os.path.join(root, each)
if os.path.isdir(filepath):
inside = os.listdir(filepath)
if “_layers” in inside:
result.append(each)
else:
for inner in inside:
result.append(os.path.join(each, inner))
return result
def _get_all_links(self, except_repo=””):
“””get links for every repository”””
result = []
repositories = self._get_repositories()
for repo in [r for r in repositories if r != except_repo]:
path = os.path.join(self.registry_data_dir, “repositories”, repo)
for link in get_links(path):
result.append(link)
return result
def prune(self):
“””delete all empty directories in registry_data_dir”””
del_empty_dirs(self.registry_data_dir, True)
def _layer_in_same_repo(self, repo, tag, layer):
“””check if layer is found in other tags of same repository”””
for other_tag in [t for t in self._get_tags(repo) if t != tag]:
path = os.path.join(self.registry_data_dir, “repositories”, repo,
“_manifests/tags”, other_tag, “current/link”)
manifest = get_digest_from_blob(path)
try:
layers = self._get_layers_from_blob(manifest)
if layer in layers:
return True
except IOError:
if self._blob_path_for_revision_is_missing(manifest):
logger.warn(“Blob for digest %s does not exist. Deleting tag manifest: %s”, manifest, other_tag)
tag_dir = os.path.join(self.registry_data_dir, “repositories”, repo,
“_manifests/tags”, other_tag)
self._delete_dir(tag_dir)
else:
raise
return False
def _manifest_in_same_repo(self, repo, tag, manifest):
“””check if manifest is found in other tags of same repository”””
for other_tag in [t for t in self._get_tags(repo) if t != tag]:
path = os.path.join(self.registry_data_dir, “repositories”, repo,
“_manifests/tags”, other_tag, “current/link”)
other_manifest = get_digest_from_blob(path)
if other_manifest == manifest:
return True
return False
def delete_entire_repository(self, repo):
“””delete all blobs for given repository repo”””
logger.debug(“Deleting entire repository %s”, repo)
repo_dir = os.path.join(self.registry_data_dir, “repositories”, repo)
if not os.path.isdir(repo_dir):
raise RegistryCleanerError(“No repository {0} found in repositories “
“directory {1}/repositories”.
format(repo, self.registry_data_dir))
links = set(get_links(repo_dir))
all_links_but_current = set(self._get_all_links(except_repo=repo))
for layer in links:
if layer in all_links_but_current:
logger.debug(“Blob found in another repository. Not deleting: %s”, layer)
else:
self._delete_blob(layer)
self._delete_dir(repo_dir)
def delete_repository_tag(self, repo, tag):
“””delete all blobs only for given tag of repository”””
logger.debug(“Deleting repository %s with tag %s”, repo, tag)
tag_dir = os.path.join(self.registry_data_dir, “repositories”, repo, “_manifests/tags”, tag)
if not os.path.isdir(tag_dir):
raise RegistryCleanerError(“No repository {0} tag {1} found in repositories “
“directory {2}/repositories”.
format(repo, tag, self.registry_data_dir))
manifests_for_tag = set(get_links(tag_dir))
revisions_to_delete = []
blobs_to_keep = []
layers = []
all_links_not_in_current_repo = set(self._get_all_links(except_repo=repo))
for manifest in manifests_for_tag:
logger.debug(“Looking up filesystem layers for manifest digest %s”, manifest)
if self._manifest_in_same_repo(repo, tag, manifest):
logger.debug(“Not deleting since we found another tag using manifest: %s”, manifest)
continue
else:
revisions_to_delete.append(
os.path.join(self.registry_data_dir, “repositories”, repo,
“_manifests/revisions/sha256”, manifest)
)
if manifest in all_links_not_in_current_repo:
logger.debug(“Not deleting the blob data since we found another repo using manifest: %s”, manifest)
blobs_to_keep.append(manifest)
layers.extend(self._get_layers_from_blob(manifest))
layers_uniq = set(layers)
for layer in layers_uniq:
if self._layer_in_same_repo(repo, tag, layer):
logger.debug(“Not deleting since we found another tag using digest: %s”, layer)
continue
self._delete_layer(repo, layer)
if layer in all_links_not_in_current_repo:
logger.debug(“Blob found in another repository. Not deleting: %s”, layer)
else:
self._delete_blob(layer)
self._delete_revisions(repo, revisions_to_delete, blobs_to_keep)
self._delete_dir(tag_dir)
def delete_untagged(self, repo):
“””delete all untagged data from repo”””
logger.debug(“Deleting utagged data from repository %s”, repo)
repositories_dir = os.path.join(self.registry_data_dir, “repositories”)
repo_dir = os.path.join(repositories_dir, repo)
if not os.path.isdir(repo_dir):
raise RegistryCleanerError(“No repository {0} found in repositories “
“directory {1}/repositories”.
format(repo, self.registry_data_dir))
tagged_links = set(get_links(repositories_dir, _filter=”current”))
layers_to_protect = []
for link in tagged_links:
layers_to_protect.extend(self._get_layers_from_blob(link))
unique_layers_to_protect = set(layers_to_protect)
for layer in unique_layers_to_protect:
logger.debug(“layer_to_protect: %s”, layer)
tagged_revisions = set(get_links(repo_dir, _filter=”current”))
revisions_to_delete = []
layers_to_delete = []
dir_for_revisions = os.path.join(repo_dir, “_manifests/revisions/sha256”)
for rev in os.listdir(dir_for_revisions):
if rev not in tagged_revisions:
revisions_to_delete.append(os.path.join(dir_for_revisions, rev))
for layer in self._get_layers_from_blob(rev):
if layer not in unique_layers_to_protect:
layers_to_delete.append(layer)
unique_layers_to_delete = set(layers_to_delete)
self._delete_revisions(repo, revisions_to_delete)
for layer in unique_layers_to_delete:
self._delete_blob(layer)
self._delete_layer(repo, layer)
def get_tag_count(self, repo):
logger.debug(“Get tag count of repository %s”, repo)
repo_dir = os.path.join(self.registry_data_dir, “repositories”, repo)
tags_dir = os.path.join(repo_dir, “_manifests/tags”)
if os.path.isdir(tags_dir):
tags = os.listdir(tags_dir)
return len(tags)
else:
logger.info(“Tags directory does not exist: %s”, tags_dir)
return -1
def main():
“””cli entrypoint”””
parser = argparse.ArgumentParser(description=”Cleanup docker registry”)
parser.add_argument(“-i”, “–image”,
dest=”image”,
required=True,
help=”Docker image to cleanup”)
parser.add_argument(“-v”, “–verbose”,
dest=”verbose”,
action=”store_true”,
help=”verbose”)
parser.add_argument(“-n”, “–dry-run”,
dest=”dry_run”,
action=”store_true”,
help=”Dry run”)
parser.add_argument(“-f”, “–force”,
dest=”force”,
action=”store_true”,
help=”Force delete (deprecated)”)
parser.add_argument(“-p”, “–prune”,
dest=”prune”,
action=”store_true”,
help=”Prune”)
parser.add_argument(“-u”, “–untagged”,
dest=”untagged”,
action=”store_true”,
help=”Delete all untagged blobs for image”)
args = parser.parse_args()
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter(u%(levelname)-8s [%(asctime)s]  %(message)s))
logger.addHandler(handler)
if args.verbose:
logger.setLevel(logging.DEBUG)
else:
logger.setLevel(logging.INFO)
# make sure not to log before logging is setup. thatll hose your logging config.
if args.force:
logger.info(
“You supplied the force switch, which is deprecated. It has no effect now, and the script defaults to doing what used to be only happen when force was true”)
splitted = args.image.split(“:”)
if len(splitted) == 2:
image = splitted[0]
tag = splitted[1]
else:
image = args.image
tag = None
if REGISTRY_DATA_DIR in os.environ:
registry_data_dir = os.environ[REGISTRY_DATA_DIR]
else:
registry_data_dir = “/opt/registry_data/docker/registry/v2”
try:
cleaner = RegistryCleaner(registry_data_dir, dry_run=args.dry_run)
if args.untagged:
cleaner.delete_untagged(image)
else:
if tag:
tag_count = cleaner.get_tag_count(image)
if tag_count == 1:
cleaner.delete_entire_repository(image)
else:
cleaner.delete_repository_tag(image, tag)
else:
cleaner.delete_entire_repository(image)
if args.prune:
cleaner.prune()
except RegistryCleanerError as error:
logger.fatal(error)
sys.exit(1)
if __name__ == “__main__”:
main()

以上就是docker使用registry搭建本地镜像仓库实例详解的详细内容,更多关于docker registry搭建本地镜像仓库的资料请关注服务器之家其它相关文章!

原文链接:https://www.cnblogs.com/renshengdezheli/p/16646969.html

声明: 猿站网有关资源均来自网络搜集与网友提供,任何涉及商业盈利目的的均不得使用,否则产生的一切后果将由您自己承担! 本平台资源仅供个人学习交流、测试使用 所有内容请在下载后24小时内删除,制止非法恶意传播,不对任何下载或转载者造成的危害负任何法律责任!也请大家支持、购置正版! 。本站一律禁止以任何方式发布或转载任何违法的相关信息访客发现请向站长举报,会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。本网站的资源部分来源于网络,如有侵权烦请发送邮件至:2697268773@qq.com进行处理。
建站知识

小知识:一斤等于多少克

2023-3-3 15:37:25

建站知识

Jenkins+Docker 一键自动化部署 SpringBoot 项目的详细步骤

2023-3-3 15:42:20

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索