Skip to content

Commit a4b7a62

Browse files
authored
Merge pull request #792 from Lucifergene/main
Auto Cleanup of Older Versions of Docker Images present in a System
2 parents 4c89e2b + 5f741a1 commit a4b7a62

File tree

2 files changed

+175
-0
lines changed

2 files changed

+175
-0
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Auto Cleanup of Older Versions of Docker Images present in a System
2+
3+
During Containerized Deployment of applications, often some VMs are particularly allotted for building the Docker Containers. Whenever a new code change takes place, automatically the CI/CD pipeline triggers the build of a new container containing the latest codes.
4+
5+
Since the VMs have a fixed Disk Size, often storage issues arise, which lead to failure in the building of the containers leading to breakage in the CICD pipeline.
6+
7+
Therefore it's necessary to remove older versions of the container images on a regular basis to avoid storage issues.
8+
9+
**This script will preserve all the docker images containing the latest tag.
10+
For a particular repository, the tag with the highest number would be preserved.
11+
A provision is made to add exception images that would be never stopped.**
12+
13+
## Setup instructions
14+
15+
Make sure to have Docker Installed in your System.
16+
Run the `main.py` file.
17+
18+
19+
## Detailed explanation of script
20+
21+
- All images with 'Alpine, Buster, Slim & Latest' tag would not be touched.
22+
- For a particular repository, the tag with the highest number would be preserved.
23+
- A provision is made to add exception images which would be never stopped.
24+
25+
## Output
26+
27+
```
28+
Deleting <Old Docker Image Name:Version>...
29+
```
30+
31+
## Author(s)
32+
33+
Avik Kundu
34+
35+
## Disclaimer
36+
37+
Be Careful Before Running this code.
38+
Docker Image deletion cannot be reverted back.

old_docker_images_auto_delete/main.py

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# Python Program to auto-delete old docker images
2+
"""
3+
Rules:
4+
1. All images with 'latest' tag would not be touched.
5+
2. For a particular repository, the tag with
6+
the highest number would be preserved.
7+
3. A provision is made to add exception images
8+
which would be never stopped.
9+
"""
10+
11+
import subprocess as sp
12+
import re
13+
import operator
14+
import itertools
15+
16+
17+
class DeleteImage:
18+
"""
19+
Deleting Old Docker Images
20+
"""
21+
def __init__(self):
22+
self.img_list = []
23+
self.hash_list = []
24+
25+
def get_all(self):
26+
"""
27+
Storing All the Docker Image Details Found on the System to a File
28+
"""
29+
file = open("temp.txt", "r+", encoding='utf-8')
30+
file.truncate(0)
31+
sp.run("sudo docker image list --format '{{.Repository}}~{{.Tag}}' >> temp.txt",shell=True , capture_output=True, check=True) # noqa
32+
file.close()
33+
34+
def is_excluded(self, tag):
35+
"""
36+
Add other exceptions here
37+
"""
38+
# Excluding all the images with Alpine, Buster, Slim & Latest Tags
39+
reg = r"alpine|buster|slim|latest"
40+
flag = re.search(reg, tag)
41+
if flag is not None:
42+
return 0
43+
return 1
44+
45+
def load_all(self):
46+
"""
47+
Loading data from the File to the Python program
48+
"""
49+
file = open("temp.txt", "r", encoding='utf-8')
50+
51+
for line in file:
52+
line = line.rstrip("\n")
53+
image = line.split('~')
54+
if self.is_excluded(image[1]):
55+
56+
regex = r"^(((\d+\.)?(\d+\.)?(\*|\d+)))(\-(dev|stage|prod))*$"
57+
match = re.search(regex, image[1])
58+
59+
img_dict = {'Repository': image[0], 'Tag': match.group(2)}
60+
self.img_list.append(img_dict)
61+
file.close()
62+
63+
def man_data(self):
64+
"""
65+
Manipulating Data to perform the reqd operation
66+
"""
67+
key = operator.itemgetter('Repository')
68+
b_key = [{'Repository': x, 'Tag': [d['Tag'] for d in y]}
69+
for x, y in itertools.groupby(sorted(self.img_list, key=key), key=key)] # noqa
70+
71+
self.img_list.clear()
72+
self.img_list = b_key.copy()
73+
74+
def sort_tag(self):
75+
"""
76+
Sorting Tags according to the Version Numbers
77+
"""
78+
79+
for img in self.img_list:
80+
temp = img['Tag'].copy()
81+
82+
for new, i in enumerate(img['Tag']):
83+
img['Tag'][new] = int(i.replace('.', ''))
84+
85+
max_len = len(str(max(abs(x) for x in img['Tag'])))
86+
template_string = '{:<0' + str(max_len) + '}'
87+
final_list = []
88+
89+
for new, i in enumerate(img['Tag']):
90+
final_list.append(template_string.format(i))
91+
92+
for i in range(0, len(img['Tag'])):
93+
hash_map = {'TagsManipulated': final_list[i], 'TagsOriginal': temp[i]} # noqa
94+
self.hash_list.append(hash_map)
95+
96+
final_list.sort()
97+
98+
img['Tag'].clear()
99+
img['Tag'].extend(final_list[:-1])
100+
101+
print(self.hash_list)
102+
print(self.img_list)
103+
104+
def hash_function(self, tag):
105+
"""
106+
Hash Function for Error Detection
107+
"""
108+
for hash_map in self.hash_list:
109+
if tag == hash_map['TagsManipulated']:
110+
temp = hash_map['TagsOriginal']
111+
break
112+
else:
113+
temp = 'Error in Manipulation'
114+
return temp
115+
116+
def remove_image(self):
117+
"""
118+
Running the Docker RMI Command to Delete the Older Versions
119+
"""
120+
for img in self.img_list:
121+
if img['Tag']:
122+
for tag in img['Tag']:
123+
val = self.hash_function(tag)
124+
image_url = img['Repository'] + ":" + val
125+
print("Deleting Image : " + image_url)
126+
sp.run("sudo docker rmi " + image_url,shell=True,capture_output=True , check=True) # noqa
127+
128+
129+
# Main Function
130+
if __name__ == "__main__":
131+
132+
docker = DeleteImage()
133+
docker.get_all()
134+
docker.load_all()
135+
docker.man_data()
136+
docker.sort_tag()
137+
docker.remove_image()

0 commit comments

Comments
 (0)