# Docker disk hygiene for the self-hosted Gitea Actions runner (home-runner-1, 192.168.1.52). # # Why this exists: every CI push builds and sha--tags a Docker image per pipeline # (rust-ci, web, docs, fedora-rpm, fedora44-rpm, ...). Those tags are never dangling, so a # plain `docker image prune` SKIPS them and they accumulate — that is what filled the disk. # Host-level, not per-repo CI, because the runner is shared (punktfunk + other orgs all benefit). # # Two tiers: trim anything older than 12h normally, AND — because a push-burst can fill 99 GB # WITHIN that 12h window (a fast iteration session hit 100% and poisoned the cargo cache with a # truncated, half-saved target/) — a burst guard that prunes ALL idle images + cache once the # disk is >85% full. Images IN USE by a running container are always protected. # # Install on the runner host (root): # cp scripts/ci/docker-prune.{service,timer} /etc/systemd/system/ # systemctl daemon-reload && systemctl enable --now docker-prune.timer # See also scripts/ci/setup-macos-runner.sh for the macOS runner. [Unit] Description=Prune aged Docker images / build cache (CI runner disk hygiene) Documentation=https://git.unom.io/unom/punktfunk Wants=docker.service After=docker.service [Service] Type=oneshot # '-' prefix: each step is independent — a no-op/failure never blocks the others. ExecStart=-/usr/bin/docker image prune -af --filter until=12h ExecStart=-/usr/bin/docker builder prune -af --filter until=12h ExecStart=-/usr/bin/docker buildx prune -af --filter until=12h ExecStart=-/usr/bin/docker container prune -f --filter until=12h # Burst guard: if STILL >85% full, prune every idle image + all build cache (in-use protected), # so a push-storm can't drive CI into ENOSPC (which truncates and poisons the actions/cargo cache). ExecStart=-/bin/sh -c 'P=$(df --output=pcent / | tr -dc 0-9); [ "$P" -ge 85 ] && { docker image prune -af; docker builder prune -af; docker buildx prune -af; } || true'