You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
On 09.09.2026 the dev instance filled its 24 GB root filesystem to 100% and stayed there. PR previews stopped starting at all (no space left on device while unpacking the image, #118), and dev's own health check could not run — Docker could not write the temporary file needed to exec it, so the container read unhealthy for thirty checks in a row while the application itself was serving normally.
50 under ghcr.io/3dbdg/platform-lite — the registry namespace from before the repository moved, dead ever since.
postgres:17, caddy:2-alpine, curlimages/curl — the three that matter.
Cleared by hand on 09.09.2026 down to six images: 24 GB used → 4.5 GB, 19 GB free, and the app went back to healthy by itself.
Why nothing caught it
Nothing in deploy/ or .github/workflows/ removes an image — no docker image prune, no rmi, no image rm. Images only ever arrive.
And the obvious reflex would not have helped: every image carries a tag (its commit sha), so there are no dangling images at all. docker image prune — which only removes untagged ones — frees exactly zero bytes here. It has to be removal by name, or prune -a with the running set protected.
What to build
A step at the end of a successful deploy that keeps the N most recent images of ghcr.io/devski/platform-lite (the running one plus a couple to roll back to) and removes the rest. Same for a preview coming down. Points to settle:
Where it belongs: deploy/remote-deploy.sh after the container is up and healthy, and deploy/preview-down.sh. It must never run before the new container is proven, or a failed deploy would have nothing to go back to.
N: three is what the by-hand cleanup kept.
Whether to guard the disk as well as the count — refuse to deploy under, say, 3 GB free and say so, the way preview-up.sh refuses past its preview cap rather than letting the kernel choose.
The dead 3dbdg namespace is gone from the instance; nothing needs to keep it out, but a prune by name should not assume a single namespace either.
Related: #111 (preview cleanup losing the race), #113 (a database per preview).
On 09.09.2026 the dev instance filled its 24 GB root filesystem to 100% and stayed there. PR previews stopped starting at all (
no space left on devicewhile unpacking the image, #118), and dev's own health check could not run — Docker could not write the temporary file needed to exec it, so the container readunhealthyfor thirty checks in a row while the application itself was serving normally.What it was
129 images, 21.82 GB, three of them in use.
ghcr.io/devski/platform-lite— one per commit, 578 MB each, pulled on every deploy since Dockerfile (standalone) + deploy on push to the dev instance, G9 #21 started deploying on 05.09.2026.ghcr.io/3dbdg/platform-lite— the registry namespace from before the repository moved, dead ever since.postgres:17,caddy:2-alpine,curlimages/curl— the three that matter.Cleared by hand on 09.09.2026 down to six images: 24 GB used → 4.5 GB, 19 GB free, and the app went back to
healthyby itself.Why nothing caught it
Nothing in
deploy/or.github/workflows/removes an image — nodocker image prune, normi, noimage rm. Images only ever arrive.And the obvious reflex would not have helped: every image carries a tag (its commit sha), so there are no dangling images at all.
docker image prune— which only removes untagged ones — frees exactly zero bytes here. It has to be removal by name, orprune -awith the running set protected.What to build
A step at the end of a successful deploy that keeps the N most recent images of
ghcr.io/devski/platform-lite(the running one plus a couple to roll back to) and removes the rest. Same for a preview coming down. Points to settle:deploy/remote-deploy.shafter the container is up and healthy, anddeploy/preview-down.sh. It must never run before the new container is proven, or a failed deploy would have nothing to go back to.preview-up.shrefuses past its preview cap rather than letting the kernel choose.3dbdgnamespace is gone from the instance; nothing needs to keep it out, but a prune by name should not assume a single namespace either.Related: #111 (preview cleanup losing the race), #113 (a database per preview).