Skip to content

Instantly share code, notes, and snippets.

@urjitbhatia
Last active May 13, 2019 21:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save urjitbhatia/dd346a209a36bf0bff88925378146deb to your computer and use it in GitHub Desktop.
Save urjitbhatia/dd346a209a36bf0bff88925378146deb to your computer and use it in GitHub Desktop.
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
Copy link

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
Copy link

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
Copy link

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