Last active
January 15, 2022 18:06
-
-
Save smajda/4e2c80c7b5e199c3663c to your computer and use it in GitHub Desktop.
Python script to delete any untagged Docker containers and images.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
import subprocess | |
import sys | |
from collections import namedtuple | |
def first_to_last(items): | |
"Return a new list where last item in items is moved to the front" | |
return items[-1:] + items[:-1] | |
def pad_list(items, pad_to=10, pad_with=''): | |
"If items is shorter than pad_to, return a new list appending pad_with up to pad_to" | |
if len(items) >= pad_to: | |
return items | |
return items + [pad_with for i in range(0, pad_to - len(items))] | |
def namedtuplify(headers, rows): | |
""" | |
Takes a list of headers and a list of lists that are rows | |
and returns a list of namedtuples. | |
- removes any whitespaces in column names in headers | |
- pads any rows that aren't long enough with empty strings | |
""" | |
max_cols = len(headers) | |
Row = namedtuple('Row', [col_name.replace(' ', '') for col_name in headers]) | |
rows = [Row(*pad_list(row, pad_to=max_cols)) for row in rows] | |
return rows | |
def get_docker_ps(): | |
# save output of ps -a as list of lists, split by whitespace, and re-organized | |
# so that the last column is first because ports and status columns alone are | |
# optionally empty, and we only have spaces to delimit columns, so we want | |
# those at the end so we can easily just pad them | |
output = [ | |
first_to_last([i.strip() for i in line.split(' ') if i.strip()]) | |
for line in subprocess.check_output(['docker', 'ps', '-a']).splitlines() | |
] | |
headers, rows = output[0], output[1:] | |
return namedtuplify(headers, rows) | |
def get_docker_images(): | |
output = [ | |
[i.strip() for i in line.split(' ') if i.strip()] | |
for line in subprocess.check_output(['docker', 'images']).splitlines() | |
] | |
headers, rows = output[0], output[1:] | |
return namedtuplify(headers, rows) | |
def untagged_containers(rows=None): | |
"List of container ids using untagged images" | |
rows = rows or get_docker_ps() | |
return [i.CONTAINERID for i in rows if re.match('[0-9a-f]{12}', i.IMAGE)] | |
def untagged_images(rows=None): | |
"List of image ids that are not tagged" | |
rows = rows or get_docker_images() | |
return [row.IMAGEID for row in rows if row.REPOSITORY == '<none>'] | |
if __name__ == '__main__': | |
container_ids = untagged_containers() | |
image_ids = untagged_images() | |
if not container_ids and not image_ids: | |
print "Nothing to cleanup!" | |
sys.exit() | |
if container_ids: | |
print "Removing containers using untagged images..." | |
for container_id in container_ids: | |
try: | |
output = subprocess.check_output(['docker', 'rm', container_id]) | |
except subprocess.CalledProcessError as e: | |
print e | |
sys.exit() | |
print output | |
if image_ids: | |
print "Removing untagged images..." | |
for image_id in image_ids: | |
try: | |
output = subprocess.check_output(['docker', 'rmi', image_id]) | |
except subprocess.CalledProcessError as e: | |
print e | |
sys.exit() | |
print output | |
print "BOOM" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment