Last active
May 13, 2019 21:16
-
-
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
This file contains 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
#!/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..." |
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..."
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
Command on line 42 fails with: "container with id **** not found". I'd add a try/except statement to continue with the script execution.