Docker Cleanup

I’m using Docker (a lot) more often these days both at home and at work, and wrote a set of short snippets to save some time fixing some painful yet simple-to-solve issues.

Abandoned Containers

Depending on the workflow, I find myself ending up with exited containers which aren’t ever going to be re-used. This can be a good thing - the container is an ephemeral artifact that we’re not coming back to. But, docker rm amazing bartik x 100 isn’t a fun exercise, even if the name generator makes interesting combos.

Which leads to:

docker ps --quiet --filter "status=exited" | \
while read container; do docker rm $container; done
  • Get all of the docker containers which have a status of exited
  • For each container_id, run docker rm $container

This one uses some bash scripting to pipe and execute a loop of commands because Docker doesn’t (to my knowledge!) provide a utility for doing this.

Abandoned Images

An impetus for the abandoned containers one-liner above, building a ton of slightly different test images means I end up with a bunch of Docker bloat. This one-liner cleans up unused images from over a week ago.

docker image prune --force --filter 'until=168h'

Unlike abandoned container cleanup, Docker provides image pruning as a utility. To pull out some of the documentation as a description of what this is doing:

  • Remove unused images which are “dangling”
    • “Not associated with a container… Dangling images are layers that have no relationship to any tagged images. They no longer serve a purpose and consume disk space” (credit to DigitalOcean for this explanation)
  • Only remove images created before given timestamp (in this case 168h = one week)
  • Don’t ask for confirmation (useful in cases where you’re automating this cleanup)

Another issue I run into is intermediate layers which aren’t old yet, but aren’t useful (having been used to in a build, but not available as separate builds). A quick way to clean those up looks like:

docker images | grep "<none>" | cut -c 29-41 | \
while read image; do docker rmi $image; done

Automating It

Combining these scripts, I can do something like this:

docker ps --quiet --filter "status=exited" | \
while read container; do docker rm $container; done && \
docker image prune --force --filter 'until=168h' && \
docker images | grep "<none>" | cut -c 29-41 | \
while read image; do docker rmi $image; done

Which makes it so that all of this can run in the background as a cron job.