docker镜像仓库删除历史版本

DevOps环境使用的镜像仓库,一个产品的版本越来越多,需要能够定时将不再使用的历史版本进行删除,编写乐意一段代码,用于删除历史版本的镜像,如下所示```

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
import argparse
import http.client
import urllib.error
import urllib.request
import json
import urllib3
import requests
REGISTRY_URL="http://10.10.70.65"
MOST_TAG_NUMBER=3
def getAllRepos(registry_repo_url):
try:
resp = urllib.request.urlopen(registry_repo_url) # type http.client.HTTPResponse
response = resp.read()
except urllib.error.HTTPError as error:
print("get repo error",error)
return json.loads(response)

def getImageDigest(repoName,tagName):
#http: // 10.10.70.65 / v2 / arch / archdemo / manifests / 1 - 1881

#curl -H "Accept: application/vnd.docker.distribution.manifest.v2 + json" -X GET -vvv -k http://10.10.70.65/v2/good_image/manifests/latest 100

try:
req = urllib.request.Request(REGISTRY_URL + "/v2/" + repoName + "/manifests/"+tagName)
req.add_header('Accept', 'application/vnd.docker.distribution.manifest.v2+json')
resp = urllib.request.urlopen(req)
# content = resp.read()
# print("all is", resp)

#print("content is ",content)
#print("digest is",resp.headers["docker-Content-Digest"])
except urllib.error.HTTPError as error:
print("get repo error",error)
return resp.headers["docker-Content-Digest"]


def deleteTagByTag(repoName, tagName):
imageDigest=getImageDigest(repoName, tagName)
try:
print("delete image %s:%s,digest is %s" %(repoName,tagName,imageDigest))
req = urllib.request.Request(REGISTRY_URL + "/v2/" + repoName + "/manifests/"+imageDigest)
req.get_method = lambda: 'DELETE'
resp = urllib.request.urlopen(req)
code = resp.getcode()
print("delet image code is ",code)
except urllib.error.HTTPError as error:
print("delete image error",error)

def cleanByRepo(repoName):
print("repos is " + repoName)
tagList = getTagsByRepoNames(REGISTRY_URL + "/v2/" + repoName + "/tags/list")# type
print("tagList is ", tagList)
if tagList["tags"] is None:
print("repo not need to clean,tag is None", repoName)
return
if len(tagList["tags"])<2:
print("repo not need to clean",repoName)
return
tagNum=0
tagNameList=[]
for tag in tagList["tags"]:
if tag.startswith("1-"):
tagNum=tagNum+1
tagNameList.append(tag)

if tagNum<MOST_TAG_NUMBER:
print("repo %s not need to clean,tag num %s is less than 4" % (repoName,tagNum))
return

#print("repo %s need to delete some tag,tag num is %s", % (repoName,tagNum))
print("repo %s need to delete some tag,tag num is %s " % (repoName,tagNum))
tagNameList.sort(reverse=True)
for index, _ in enumerate(tagNameList):
if index>3:
deleteTagByTag(repoName,tagNameList[index])



def getTagsByRepoNames(registry_repo_url):
try:
resp = urllib.request.urlopen(registry_repo_url)
response = resp.read()
except urllib.error.HTTPError as error:
print("get repo error",error)
return json.loads(response)

def main():
print("get all repo")
response=getAllRepos(REGISTRY_URL + "/v2/_catalog?n=100000")
print("response is ",response)
print("repos list is",response["repositories"])

for repo in response["repositories"]:
cleanByRepo(repo)



if __name__ == '__main__':
main()

上面的代码能保存最新的几个版本的镜像,我这里的版本镜像是以“1-” 开头为标识,执行完该代码后,还需要在镜像仓库的节点,执行以下命令,进行存储回收:```

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