Docker Prune via Systemd
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