Files
werkator/docs/prs/2026-09-19-PR#80-prune-anonymous-volumes.md
ea19be0c7f
werkator build succeeded after 02:23
werkator/deploy build succeeded after 00:08
fix(init): the nightly Docker cleanup removes anonymous volumes too (#80)
docker system prune never touches a volume, so a Docker host collected
281 PostgreSQL data directories. Anonymous volumes are told by their
64-digit hex name, because docker volume prune spares named volumes
only since Docker 23.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: mhoennig <michael@hoennig.de>
Reviewed-on: #80
2026-09-19 21:36:34 +02:00

61 lines
3.0 KiB
Markdown

> **WARNING:** This document describes only the change applied in this PR.
> It may already be outdated once the next PR is merged.
> Historic PR-documentation is not maintained along with new PRs — treat it as a snapshot, not as current documentation.
## The Problem
The Docker host vm4006 held 283 dangling volumes on 2026-09-19, 17.7 GB.
281 of them were anonymous, each a PostgreSQL data directory of about 45 MB.
The nightly `werkator-docker-prune.timer` had run every night and reported success.
The unit runs `docker system prune -af`, and that command never removes a volume without `--volumes`.
The flag was left out on purpose: the per-repository Gradle cache volumes have to survive the cleanup.
So nothing on the host ever removed a volume.
The volumes came from the repository's smoke test, which removes its throw-away database container with `docker rm -f`, without `-v`.
The image declares its data directory as a volume, so every build left one behind.
That is fixed in the repository, but a CI host should not depend on every build script getting this right.
## Non-Goals
- Named volumes stay, whoever created them; a stale cache volume from before the rename is removed by hand.
- No pruning from inside Werkator; the cleanup stays a systemd unit of the host.
- No change to the timer.
## The Scenarios
### Feature: the nightly cleanup removes the volumes nobody named
#### Scenario#80.01: Anonymous volumes go, cache volumes stay
- **Given** dangling volumes on a Docker host, some named by Docker with 64 hex digits, one named `werkator-gradle-<repo>`
- **When** the nightly prune service runs
- **Then** the hex-named volumes are removed after the containers have been pruned
- **And** the Gradle cache volume is still there
- **And** a volume held by a running container is untouched, because it is not dangling
##### Verified by
- [SystemdServiceFilesTest](../../src/test/kotlin/de/hoennig/werkator/commands/SystemdServiceFilesTest.kt) — the two `ExecStart` lines in order, and the unit's own filter run through `sh` against a hex name, a cache volume name and a 65-digit name
## The Solution
`SystemdServiceFiles.pruneServiceContent` gets a second `ExecStart`:
`docker volume ls -q -f dangling=true | grep -Ex "[0-9a-f]{64}" | xargs -r docker volume rm`.
The name is the criterion because it holds on every Docker version.
`docker volume prune` spares named volumes only since Docker 23; before that it takes every unused volume, and at 02:00 the Gradle caches are unused.
The `com.docker.volume.anonymous` label exists only since 23 as well.
The step is not prefixed with `-`: a volume that cannot be removed fails the unit, which is how the host says so.
## Additional Changes
- `docs/deployment.md` describes the step and how an existing host gets it: `init --systemd` rewrites the units, then `systemctl --user daemon-reload`.
- Version 1.21.3 with its release note.
## Follow-up PRs
- None in this repository.
vm4006 needs the new version and one `init --systemd`; its 281 volumes were removed by hand on 2026-09-19.