Skip to main content

Docker Prune via Systemd

· 3 min read
Stephan Hochdörfer
Head of IT Business Operations

To have the most flexibility for our CI pipelines, we use the Docker runner in our GitLab CI environment. This allows us to easily customize each job in each build pipeline for each of our customers, ensuring they match our specific needs.

While this works great, it has a minor downside. GitLab CI does not automatically delete the Docker images and Docker volumes after a certain period. Also, even Nomad does not take care, as the GitLab CI runner is running as a Nomad job, but the Docker containers spawned for each build job run independently of Nomad, and thus it has no idea about it.

So the best solution is to take matters into our hands and regularly run docker system prune and docker volume prune to clean up.

Docker system prune

To regularly delete Docker images, I've set up a docker-prune.service Systemd job in the /etc/systemd/system directory:

[Unit]
Description=Prune old Docker images

[Service]
Type=oneshot
ExecStart=docker system prune -af --filter "until=24h"

This will delete all images that have not been in use for more than 24 hours. This may be a bit too aggressive, but since most of our CI images are stored in our own Docker registry running on the same network, download bandwidth is not really an issue.

To start the job, run the following command: systemctl start docker-prune.service

For letting the service run as a cron job, a timer docker-prune.timer file is needed and it has to be placed in the /etc/systemd/system directory:

[Unit]
Description=Purge old Docker images regularly

[Timer]
Unit=docker-prune.service
OnCalendar=*-*-* 01:30:00
Persistent=true

[Install]
WantedBy=timers.target

To enable the timer to start at boot, run the following command: systemctl enable docker-prune.timer

This sets up the timer it does not start it right now. To start the timer so it begins scheduling, according to its defined interval, run the following command: systemctl start docker-prune.timer

Docker volume prune

Removing Docker images is one part of the coin; the other is deleting volumes no longer in use. Especially on CI servers where lots and lots of data is downloaded, volumes can grow quickly and occupy a lot of disk space.

Since the docker system prune command is not able to work with the --fiter and --volumes flag, I decided to set up an additional Systemd job for cleaning up all unnecessary volumes.

Similarly to the docker-prune.service Systemd job, let's add a file docker-volume-prune.service in the /etc/systemd/system directory:

[Unit]
Description=Prune Docker volumes

[Service]
Type=oneshot
ExecStart=docker volume prune --all

This command will delete all unused volumes, not just anonymous ones.

To start the job, run the following command: systemctl start docker-volume-prune.service

For letting the service run as a cron job, a timer docker-volume-prune.timer file is needed and it has to be placed in the /etc/systemd/system directory:

[Unit]
Description=Purge Docker volumes regularly

[Timer]
Unit=docker-volume-prune.service
OnCalendar=*-*-* 02:30:00
Persistent=true

[Install]
WantedBy=timers.target

To enable the timer to start at boot, run the following command: systemctl enable docker-volume-prune.timer. And to start the timer, the following command needs to run: systemctl start docker-volume-prune.timer