Docker prune reports 0 B reclaimed while a buildx builder's volume holds 73 MB of cache
A dev.to post measured 73 MB of buildx cache under Local Volumes on Docker Engine 29.9.0 while Build Cache read 0 B. docker builder prune works only on the selected builder, so CI hosts need to clean the other builder's volume separately.
The Engineer · Build desk
What happened
- docker builder prune acts on the selected builder, and in the post's test that was the daemon's own.
- docker buildx rm --keep-state removes the builder but keeps its volume, and afterward nothing refers to that volume.
- In a second case, after a daemon switched to the containerd image store, 71.8M of overlay2 data stayed on disk while docker images came back empty and every df row read 0B.
Why it matters
- exposure A disk alert keyed to the Build Cache row of docker system df reads 0 B on a host whose cache sits in the Local Volumes row.
- constraint The remedy takes a builder name, so a host with several docker-container builders needs a prune per builder.
- decision A daemon moved to the containerd store keeps its old overlay2 data hidden until it is switched back, so anything worth keeping needs docker save first.
Read the 73 MB with care. The test build added 30 MB [4], but the Local Volumes row shows 73.31 MB [5]. That leaves about 43 MB the build does not account for [20]. The post calls the whole figure build cache [6] and does not break it down. The same row lists a reclaimable figure of 114.7 kB, or 0% [5]. The 0 B from `docker builder prune` is therefore a correct report on the daemon's own builder, whose Build Cache row is empty [5][7].
The volume is easy to find once you know the name. The node is usually the builder name plus 0 [3], so the builder `ci` in the test would own `buildx_buildkit_ci0_state` [21]. The post lists four checks [10]. `docker volume ls --filter name=buildx_buildkit_` returns one volume per docker-container node. `docker system df -v | grep buildx_buildkit_` gives sizes. `docker buildx ls` shows which builder each node belongs to. `docker buildx du --builder <name>` lists that builder's cache record by record.
The failure case is a host that drifted. A CI host that once ran `docker buildx create --use` and was later switched back keeps growing in a volume that `docker builder prune` never touches [8]. The post's fix is `docker buildx prune --builder <name>`. Add `--keep-storage 10gb` to keep a working set, or set a GC policy in that builder's `buildkitd.toml` [11].
The same symptom has a second cause. In both of the post's cases, `docker system prune -af` reports 0B while `df -h` shows the disk filling [1]. Docker Desktop and fresh Engine 29 installs use the containerd image store [12]. When a daemon is switched to it, the classic overlay2 images and containers are not deleted [13]. Docker's docs, quoted in the post, say: "Your overlay2 data remains on disk but becomes hidden." [14] On a real machine, the post says, the hidden amount is whatever existed before the switch, often many gigabytes [22]. A third case, moby#47089, is an `overlay2/` directory far larger than images, containers and build cache combined [17].
These are one author's numbers from a disposable `docker:dind` container [1][19]. The post discloses that Claude helped draft it from the dockdu repository's measurement log, and it closes by describing dockdu, a CLI that has run these checks since 0.4.0 [19][18]. According to the post, dockdu deletes nothing, and its Docker client rejects every request except GET or HEAD calls to four read endpoints [18].
A 30 MB build on a throwaway daemon does not indicate scale for a real CI host. We'd expect the behavior to transfer to any host with a docker-container builder that is not the selected one. The sizes will not transfer. The volume naming is cited in the post to the buildx source [2].
What to watch
- Whether a rerun on a disposable docker:dind container shows the builder volume's du -sk unchanged after docker system prune -af, as the post's 0B suggests.
- Whether a later Docker Engine release changes how docker system df labels buildx state volumes. The post measured only 29.9.0.
- Whether the leftover-directory check for moby#47089 holds up on a real host with many gigabytes in overlay2.
Clarity's read
What the record supports and how the coverage leans. The claims behind it follow.
Reality
- Evidence58
- Adoption
- Insufficient
- Hype gap+15
- Incentives40
- Confidence65
Claim ledger
Ranked by verification strength, evidence, and original report placement.
- [1]
In the post's two cases, docker system df says the build cache is empty, docker system prune -af reports Total reclaimed space: 0B, and df -h still shows the disk filling; both were measured on Docker Engine 29.9.0.
- [2]
docker buildx create --driver docker-container starts BuildKit in its own container, buildx_buildkit_<node>, and the builder keeps its whole state, including its build cache, in a volume named buildx_buildkit_<node>_state (the post cites the buildx source).
- [3]
The node in the container and volume name is usually the builder name plus 0.
- [4]
The measured setup was one builder named ci and one build that added 30 MB.
- [5]
In the post's docker system df output, the Local Volumes row shows 2 total, 1 active, size 73.31MB, reclaimable 114.7kB (0%), while the Build Cache row shows 0 total, 0 active, 0B, 0B.
- [6]
The post states that the 73 MB of build cache is in the Local Volumes row.
- [7]
docker builder prune works on the selected builder, which in the post's test was the daemon's own.
- [8]
A CI host that once ran docker buildx create --use and was later switched back keeps growing in a volume that docker builder prune never touches.
- [9]
docker buildx rm --keep-state removes the builder but keeps the volume; nothing then refers to it, so it only shows up as an unused volume.
- [10]
The post's by-hand checks are: docker volume ls --filter name=buildx_buildkit_ (one per docker-container node); docker system df -v | grep buildx_buildkit_ (sizes); docker buildx ls (which builder each node belongs to); docker buildx du --builder <name> (that builder's cache, record by record).
- [11]
To free the cache the post gives docker buildx prune --builder <name>, adds --keep-storage 10gb to keep a working set, or suggests setting a GC policy in that builder's buildkitd.toml.
- [12]
Docker Desktop and fresh Engine 29 installs use the containerd image store.
- [13]
If a daemon is switched to the containerd image store, the images and containers of the classic overlay2 store are not deleted.
- [14]
Your overlay2 data remains on disk but becomes hidden.
- [15]
In the post's test, after alpine:3.22 and nginx:1.29-alpine were pulled under the graph driver and the same data root was started with --feature containerd-snapshotter=true, docker images was empty, every docker system df row read 0B, docker system prune -af reclaimed 0B, and /var/lib/docker/overlay2 still held 71.8M.
- [16]
To free the hidden data, switch the daemon back to overlay2; the old images and containers reappear and can be removed normally, and anything worth keeping should be saved with docker save first.
- [17]
A third case, moby#47089, is an overlay2/ directory far larger than images, containers and build cache together.
- [18]
dockdu, a read-only CLI that explains Docker disk usage, has done these checks since 0.4.0; the post says it never deletes anything and its Docker client refuses any request other than GET/HEAD on four read endpoints.
- [19]
The post discloses that it was drafted with AI assistance (Claude) from measurements recorded in the dockdu repository, and says every number comes from the measurement log and can be reproduced on a disposable docker:dind container.
- [20]
The Local Volumes row exceeds the 30 MB build by about 43 MB.
- [21]
For a builder named ci, the node is ci0 and the state volume would be buildx_buildkit_ci0_state.
- [22]
On a real machine the hidden overlay2 amount is whatever existed before the switch, often many gigabytes, according to the post.
Get this ledger inside ChatGPT. Ask about any of our stories and the answer brings its figure, each claim’s verdict and the sources. Free, no account.
Sources
1 independent publisher whose own reporting we read for this story.
- dev.todocker builder prune freed 0 B: two places Docker keeps disk space that no prune reaches
1 article · October 14, 2026
Topics and entities
Follow any of these and your For You feed starts watching them — no settings page required.