How to make docker evict stuff

Stop docker slowly filling your disk

Docker is a popular local disk cache, masquerading as virtualisation technology.

The problem is that, unlike a real cache, Docker doesn't handle it's own "eviction" - nothing is ever deleted. The means that docker slowly grows to fill your whole disk. When working on a commercial project, (re)building big images over and over this can happen quite quickly: in weeks.

Eviction, of a kind

The best way, as far as I know, to do some eviction is by running

docker system prune --all --force --filter "until=432h"

This "prunes" docker data.

Why 22 days? It's often a good idea to ensure that periods for things like cleanup, log retention, etc don't align with human periods like calendar weeks. Otherwise you find yourself coming in every Monday morning to find the entire cache has been cleared, or that bugs that happen at end-of-month don't have the logs from the previous month recorded. Keep sysadmin periods at n+a_little_bit.

And also note: this isn't real LRU ("least recently used") eviction. Real caches, like memcache, don't evict old stuff, they evict stuff that isn't being used very often, which is different. Unfortunately docker doesn't seem to record access times for it's layers/volumes/whatever so proper LRU is impossible. Instead, you just have to suffer everything occasionally getting deleted.

Automating it

No one wants "just one more thing to remember" so best to set the command to run automatically. Here's how with systemd:

# $HOME/.config/systemd/docker-prune.timer
[Unit]
Description=Prune docker data

[Timer]
OnCalendar=daily
RandomizedDelaySec=1h # ensure it doesn't happen at boot/resume from suspend
Persistent=true

[Install]
WantedBy=timers.target
# $HOME/.config/systemd/docker-prune.timer
[Unit]
Description=Prune unused Docker data
Documentation=https://docs.docker.com/engine/reference/commandline/system_prune/

[Service]
Type=oneshot
ExecStart=/usr/bin/docker system prune --all --force --filter "until=528h"

Then you:

systemctl --user daemon-reload
systemctl --user enable docker-prune