|
| 1 | +#!/usr/bin/env python |
| 2 | +# -*- coding: utf-8 -*- |
| 3 | +""" |
| 4 | + File Name: clean_lainnode_image.py |
| 5 | + Author: longhui |
| 6 | + Created Time: 2018-09-20 11:00:50 |
| 7 | + Descripthion: This script is used to clean the docker images on lain node, and keep several latest |
| 8 | +""" |
| 9 | + |
| 10 | +import sys |
| 11 | +import re |
| 12 | +import logging |
| 13 | +import argparse |
| 14 | +import pprint |
| 15 | +from logging import handlers |
| 16 | +from subprocess import check_output, STDOUT, CalledProcessError, call |
| 17 | + |
| 18 | + |
| 19 | +LOGFILE = '/var/log/clean_lainnode_images.log' |
| 20 | + |
| 21 | +log = logging.Logger(__file__) |
| 22 | +log.setLevel(logging.INFO) |
| 23 | +handler = logging.StreamHandler(sys.stdout) |
| 24 | +handler.setLevel(logging.DEBUG) |
| 25 | +handler.setFormatter( |
| 26 | + logging.Formatter("[%(levelname)s] %(asctime)s,%(lineno)4d, %(funcName)s : %(message)s", '%Y-%m-%d %H:%M:%S')) |
| 27 | +fileHandler = handlers.RotatingFileHandler(LOGFILE, 'a', 10 * 1024 * 1024, 2) |
| 28 | +fileHandler.setLevel(logging.DEBUG) |
| 29 | +fileHandler.setFormatter( |
| 30 | + logging.Formatter("[%(levelname)s] %(asctime)s,%(lineno)4d, %(funcName)s : %(message)s", '%Y-%m-%d %H:%M:%S')) |
| 31 | +log.addHandler(handler) |
| 32 | +log.addHandler(fileHandler) |
| 33 | + |
| 34 | +release_reg = re.compile(r'release-(\d+)-') |
| 35 | +meta_reg = re.compile(r'meta-(\d+)-') |
| 36 | + |
| 37 | + |
| 38 | +def get_images(): |
| 39 | + """ |
| 40 | + return a dict with its value as {'release':[],'meta':[]} |
| 41 | + :return: |
| 42 | + """ |
| 43 | + all_images = {} |
| 44 | + cmd = "docker images --format {{.Repository}},{{.Tag}} --no-trunc" |
| 45 | + try: |
| 46 | + output = check_output(cmd, stderr=STDOUT, shell=True) |
| 47 | + except CalledProcessError as e: |
| 48 | + log.error("Exceptions when run cmd:%s, error: %s", cmd, str(e)) |
| 49 | + return all_images |
| 50 | + |
| 51 | + images_list = output.splitlines() |
| 52 | + for image in images_list: |
| 53 | + image_name, tag = image.split(',') |
| 54 | + all_images.setdefault(image_name, dict(release=[], meta=[])) |
| 55 | + res = release_reg.match(tag) |
| 56 | + if res: |
| 57 | + all_images[image_name]["release"].append('{}:{}'.format(image_name, tag)) |
| 58 | + else: |
| 59 | + res = meta_reg.match(tag) |
| 60 | + if res: |
| 61 | + all_images[image_name]['meta'].append('{}:{}'.format(image_name, tag)) |
| 62 | + |
| 63 | + return all_images |
| 64 | + |
| 65 | + |
| 66 | +def remove_images(images_list=None, keep_num=3): |
| 67 | + """ |
| 68 | + :param images_list: images list to delete |
| 69 | + :param keep_num: the num to keep for latest tags |
| 70 | + :return: None |
| 71 | + """ |
| 72 | + if not images_list: |
| 73 | + return |
| 74 | + |
| 75 | + sort_images = sorted(images_list, key=lambda f: int(f.split(':')[1].split("-")[1]), reverse=True) |
| 76 | + delete_images = sort_images[keep_num:] |
| 77 | + |
| 78 | + log.debug("To delete: %s", pprint.pformat(delete_images)) |
| 79 | + for image in delete_images: |
| 80 | + log.debug("Start to rm tag: %s", image) |
| 81 | + ret = call(['docker', 'rmi', image]) |
| 82 | + if ret != 0: |
| 83 | + log.error("Remove image failed: %s", image) |
| 84 | + |
| 85 | + |
| 86 | +if __name__ == "__main__": |
| 87 | + parser = argparse.ArgumentParser(description="Clean docker images and keep several latest tags") |
| 88 | + |
| 89 | + parser.add_argument("--debug", dest="debug", action="store_true", help="Run in debug mode") |
| 90 | + parser.add_argument("--keep-num", dest="keep_num", nargs='?', default=3, type=int) |
| 91 | + |
| 92 | + args = parser.parse_args() |
| 93 | + log.info(args) |
| 94 | + if args.debug: |
| 95 | + log.setLevel(logging.DEBUG) |
| 96 | + |
| 97 | + all_images = get_images() |
| 98 | + for image_name, tags in all_images.iteritems(): |
| 99 | + log.info("Start to remove release tags in image: %s", image_name) |
| 100 | + remove_images(tags["release"], args.keep_num) |
| 101 | + |
| 102 | + log.info("Start to remove meta tags in image: %s", image_name) |
| 103 | + remove_images(tags['meta'], args.keep_num) |
0 commit comments