/var/lib/docker grows until it becomes the whole disk problem. The fix is one command, but running it blind is how people delete the base image they were about to build on. Look first, then prune.
1. See where the space went
$ clai show how much disk space docker is using and how much is reclaimable→ docker system dfTYPE TOTAL ACTIVE SIZE RECLAIMABLEImages 47 13 28.88GB 20GB (69%)Containers 16 9 126.8MB 513.8kB (0%)Local Volumes 38 7 6.311GB 4.084GB (64%)Build Cache 181 0 0B 0B
Read the RECLAIMABLE column before anything else. Here images are the problem, volumes are second, containers are noise.
2. The safe sweep
$ clai remove stopped containers, dangling images and unused networks→ docker system prune
Plain prune takes stopped containers, dangling images (layers with no tag left), unused networks and build cache. It does not touch tagged images or volumes. This is the one you can run without thinking about it.
3. The aggressive sweep
$ clai remove all images that no running container is using→ docker system prune -a⚠ CAUTION — removes every image not used by a running container
-a widens "unused" from untagged to not currently in use by a running container. Your carefully pulled 4 GB base image counts as unused if nothing is running right now — you'll re-download it on the next build.
4. Volumes: the space nobody expects
$ clai list docker volumes that no container is using→ docker volume ls -qf dangling=true
Prune skips volumes by default, deliberately — that's where databases live. List them first, recognise the names, and only then decide. docker volume prune deletes data that has no backup by definition.
5. Just the build cache
$ clai clear docker build cache older than a week→ docker builder prune --filter 'until=168h'
On a CI box this is usually the biggest and safest win. --filter until= lets you keep recent layers so the next build is still fast.
6. Stop it happening again
$ clai limit docker container log files to 10 megabytes and 3 files→ sudo tee /etc/docker/daemon.json <<'EOF'{"log-driver":"json-file","log-opts":{"max-size":"10m","max-file":"3"}}EOF
Container logs have no rotation by default. This is the single setting that prevents the most common repeat offence. It applies to containers created after a daemon restart.
Gotchas
prune -awith nothing running deletes everything. The definition of "in use" is a running container, not an image you like. Start your stack first, or use--filter 'until=720h'instead.- Prune doesn't shrink a full disk on Docker Desktop. On macOS and Windows the VM disk image doesn't return space to the host automatically.
- A pruned volume is gone. There is no trash. Back up before you prune volumes, every time.
Related questions
What's the difference between docker system prune and docker image prune -a? system prune covers containers, networks, images and build cache in one pass; image prune -a only removes images, and removes tagged ones too.
Why is /var/lib/docker/overlay2 so big? That's image and container layers. Don't delete anything in there by hand — the metadata lives elsewhere and you'll corrupt the image store. Use prune.
Can I see which image is the biggest? docker image ls --format '{{.Size}}\t{{.Repository}}:{{.Tag}}' | sort -rh sorts them.
See also
- Docker and Kubernetes muscle memory, replaced
- df says the disk is full, du says it isn't
- Sweep old logs and backups with one sentence
CliAI marks prune -a as CAUTION and asks before it runs — because the difference between the two prunes is 20 GB of re-downloads. Install it in one line.