Prevent docker from filling up your disk

Deploying docker container as part of your continuous integration can cause your disk to fill up pretty quick. Docker does reuse the layers that did not change between deployments. But still, that last layer with you .war or .js bundle can take a few hundred megabytes. Taking into account, that you should be deploying a new version of every update of the master branch, this can take up a gigabyte every day. And you don’t really need all those old images and containers on your dev environment.

Docker, by itself, does not do any cleaning up. You need to tell it to. There is the command that removes unused data:

docker system prune

But still, you need to run it periodically by yourself. Also, you might want to keep those not-that-old container logs for debug purposes.

Automatic cleaning

The simplest, yet sufficient solution is to run this line daily:

docker system prune -af  --filter "until=$((30*24))h"

The -a flag will remove all unused images not just dangling ones. The other one (-f) prevents the confirmation prompt. That’s good, cause will be running this command from cron. Last flag (--filter) causes the procedure to spare the images and stopped containers from the last month.

Docker, as it is written in go, parses time duration strings using go’s build in function. The downside is that the longest unit is supports is h - hour. That’s why we can’t just pass until=30d. We need to specify the number of hours. Writing until=720h does not obviously tell the next maintainer we meant a month. Still, we can use bash’s ability to do basic math. At least the expression 30*24h quickly hints we meant 30 days.
Thus --filter "until=$((30*24))h".

One last thing. Make the system run list line daily.

The /etc/cron.daily directory allows us to not even bother with cron expressions. Just create a file /etc/cron.daily/docker-prune. Make is executable with

chmod +x /etc/cron.daily/docker-prune

It’s contents is just:

#!/bin/bash
docker system prune -af --filter "until=$((30*24))h"

Optional logging

If you’d like to have some basic logging you can extend the script like this:

#!/bin/bash
log=/var/lib/docker/prune.log
date +'=== %Y.%m.%d %H:%M ===' >> $log
docker system prune -af --filter "until=$((30*24))h" >> $log

This will cause every execution to add a timestamp and docker’s output to /var/lib/docker/prune.log file.

docker  cron