My disk was filling up with old Docker images. I got a low disk space warning and traced 80GB back to Docker. Here’s how to reclaim space.
How much space can you reclaim? Link to heading
First, see what Docker is using:
docker system df
This shows you a breakdown by images, containers, and volumes. In my case:
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 47 12 35.6GB 28.4GB (79%)
Containers 8 3 127.3MB 84.2MB (66%)
Local Volumes 15 2 2.1GB 1.8GB (85%)
Build Cache 0 0 0B 0B
Nearly 30GB reclaimable. Worth the cleanup.
Cleanup commands Link to heading
Remove unused containers, networks, and images:
docker system prune
This is my go-to command. It removes:
- All stopped containers
- All networks not used by at least one container
- All dangling images (untagged)
- All build cache
Add -a to also remove images not referenced by any container:
docker system prune -a
Warning: this will remove images you might want to keep. I rarely use -a unless I’m doing a complete cleanup.
Just remove unused images:
docker image prune
Remove stopped containers:
docker container prune
See what’s using space:
docker images
See all containers including stopped ones:
docker ps -a
What NOT to prune Link to heading
Don’t prune volumes unless you’re certain. Volumes contain data like databases. Running:
docker volume prune
…will delete volumes not attached to a container. I accidentally deleted a local Postgres database this way once. Not fun.
If you’re using docker-compose, docker compose down -v removes volumes for that specific compose project, which is safer than a blanket prune.
Don’t prune on production systems without understanding what’s running. A “dangling” image might be in use by a container that’s temporarily stopped for maintenance. In production, targeted cleanup is preferable over blanket prunes.
Automating cleanup in CI Link to heading
In CI environments, Docker images and build cache accumulate quickly. Most CI systems don’t clean up automatically, so you’ll eventually run out of disk space.
I add cleanup steps to CI pipelines:
# GitHub Actions example
- name: Clean up Docker
if: always()
run: |
docker system prune -af --volumes
The if: always() ensures cleanup runs even if tests fail. The -f flag skips confirmation prompts.
For self-hosted runners, a cron job that runs nightly works well:
# /etc/cron.daily/docker-cleanup
#!/bin/bash
docker system prune -af --filter "until=24h"
The --filter "until=24h" keeps anything from the last 24 hours, which prevents removing images that might be needed by running builds.
My typical reclamation Link to heading
After running docker system prune, I usually reclaim:
- Development machine: 10-20GB (I clean up weekly)
- CI runner: 50-100GB (if I’ve been lazy about automation)
- Build server: 200GB+ (one-off cleanup when adding this to automation)
It’s worth checking periodically. Docker doesn’t clean up after itself by default.
For more details on what gets removed, the Docker prune documentation explains each command and filter option.