Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Python script to force kill docker containers older than a certain number of minutes
#!/usr/bin/python
# Quick and dirty script to kill containers older than some number of minutes
# Kills all containers older than 60 minutes by default!
import sys
import subprocess
from sets import Set
CMD_DOCKER_CONTAINERS_WITH_AGE = 'docker ps -a --format "{{.ID}} {{.Status}}"'
CMD_DOCKER_CONTAINERS_BEFORE = 'docker ps -aq -f before=%s'
# Find containers and their age
containers = subprocess.check_output(CMD_DOCKER_CONTAINERS_WITH_AGE, shell=True).rstrip().split('\n')
# Kill all containers older than this value
try:
MAX_ALLOWED_AGE_MINS = int(sys.argv[1])
except:
print "Input must be an integer number of minutes"
print "Any containers older than that will be killed"
sys.exit(1)
# Find the containers that are older than MAX_ALLOWED_AGE_MINS
containerIdsToKill = Set()
for c in containers:
if not c:
continue
parts = c.rstrip().split(' ')
containerId = parts[0]
age = parts[-2]
agePeriod = parts[-1]
if any(period in c for period in ['hour', 'day', 'week']) \
or (agePeriod == 'minutes' and int(age) > MAX_ALLOWED_AGE_MINS):
print "Killing container: %s Age: %s %s" % (containerId, age, agePeriod)
containerIdsToKill.add(containerId)
# Find all containers older than these containers - this ensures we capture stuck containers
# by using a 'before' filter.
containerIdsToKillBefore = []
for containerId in containerIdsToKill:
containersBefore = subprocess.check_output(CMD_DOCKER_CONTAINERS_BEFORE % containerId, shell=True)
containerIdsToKillBefore = containersBefore.rstrip().split('\n')
# Add these to our set of containers to kill
containerIdsToKill.update(containerIdsToKillBefore)
if not containerIdsToKill:
print "No containers old enough to kill"
else:
# Kill 'em!
killList = ' '.join(containerIdsToKill)
killCall = subprocess.Popen('docker rm -f %s' % killList, shell=True, stdout=subprocess.PIPE)
killCall.wait()
print "Done..."
@dgarana

This comment has been minimized.

Copy link

@dgarana dgarana commented Sep 11, 2018

Command on line 42 fails with: "container with id **** not found". I'd add a try/except statement to continue with the script execution.

@dbellizzi

This comment has been minimized.

Copy link

@dbellizzi dbellizzi commented May 13, 2019

Here's an update to fix some of the not found ones. Docker before is broken in some versions, and in the latest, it is fixed only for name and can't be used with containerId:

#!/usr/bin/python

# Quick and dirty script to kill containers older than some number of minutes
# Kills all containers older than 60 minutes by default!

import sys
import subprocess
from sets import Set

CMD_DOCKER_CONTAINERS_WITH_AGE = 'docker ps -a --format "{{.ID}} {{.Names}} {{.Status}}"'
CMD_DOCKER_CONTAINERS_BEFORE = 'docker ps -aq -f before=%s'

# Find containers and their age
containers = subprocess.check_output(CMD_DOCKER_CONTAINERS_WITH_AGE, shell=True).rstrip().split('\n')

# Kill all containers older than this value
try:
        MAX_ALLOWED_AGE_MINS = int(sys.argv[1])
except:
        print "Input must be an integer number of minutes"
        print "Any containers older than that will be killed"
        sys.exit(1)

# Find the containers that are older than MAX_ALLOWED_AGE_MINS
containerIdsToKill = Set()
containerNamesToBefore = Set()
for c in containers:
        if not c:
                continue
        parts = c.rstrip().split(' ')

        isUp = parts[2] == "Up"
        if not isUp:
                continue
        containerId = parts[0]
        age = parts[-2]
        agePeriod = parts[-1]
        name = parts[1]
        if any(period in c for period in ['hour', 'day', 'week']) \
	or (agePeriod == 'minutes' and int(age) > MAX_ALLOWED_AGE_MINS):
                print "Killing container: %s Age: %s %s" % (containerId, age, agePeriod)
                containerIdsToKill.add(containerId)
                containerNamesToBefore.add(name)

# Find all containers older than these containers - this ensures we capture stuck containers
# by using a 'before' filter.
containerIdsToKillBefore = []
for containerName in containerNamesToBefore:
        containersBefore = subprocess.check_output(CMD_DOCKER_CONTAINERS_BEFORE % containerName, shell=True)
	containerIdsToKillBefore = containersBefore.rstrip().split('\n')

# Add these to our set of containers to kill
containerIdsToKill.update(containerIdsToKillBefore)

if not containerIdsToKill:
        print "No containers old enough to kill"
else:
     	# Kill 'em!
        killList = ' '.join(containerIdsToKill)
        print "Actually killing: %s" % (killList)
        killCall = subprocess.Popen('docker rm -f %s' % killList, shell=True, stdout=subprocess.PIPE)
        killCall.wait()
print "Done..."
@dbellizzi

This comment has been minimized.

Copy link

@dbellizzi dbellizzi commented May 13, 2019

Not sure we actually need the before check anymore though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment