Every image you pull, every build you run and every container you replace leaves something behind. On a VPS with a modest disk, Docker's leftovers can grow to tens of gigabytes. This guide shows how to measure what Docker is using and remove only what is safe to remove.
Before you start
- A Linux VPS with Docker Engine installed.
- A user that can run
dockercommands. - All the containers you care about should be running. Prune commands treat stopped containers and the images they use as unused.
Warning: Some prune commands delete data permanently. Read each section before running its command, and never add --volumes unless you have checked which volumes will go.
Check what Docker is using
Start with a summary:
docker system dfThe output looks like this:
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 24 9 8.1GB 5.3GB (65%)
Containers 11 9 210MB 12MB (5%)
Local Volumes 14 8 3.4GB 900MB (26%)
Build Cache 96 0 2.7GB 2.7GBRECLAIMABLE is what pruning could free. For a per-item breakdown, add -v:
docker system df -vAlso compare with the whole disk, because logs are not counted in docker system df:
df -h /
sudo du -sh /var/lib/docker/containersIf the containers folder is large, the cause is container logs. Fix that with View and rotate Docker container logs.
Remove stopped containers
docker container pruneThis deletes containers that are not running. Their writable layers go with them, but named volumes are kept.
Remove unused images
Dangling images are untagged layers left behind when you pull or build a new version. Removing them is always safe:
docker image pruneTo remove every image that no container uses, including tagged ones:
docker image prune -aThe next docker compose up or docker run downloads any removed image again, so the only cost is bandwidth and time. You can keep recent images by age:
docker image prune -a --filter "until=168h"That removes only unused images created more than seven days ago.
Remove build cache
If you build images on the server, the cache can be the largest item:
docker builder pruneAdd -a to remove all build cache, not only dangling entries. The next build will be slower because it starts from scratch.
Remove unused networks
docker network pruneNetworks take no disk space, but clearing old ones avoids subnet clashes.
Volumes: check before you prune
Volumes hold databases and uploads. A volume can look unused simply because its container is stopped or was recreated under a different project name.
List volumes that no container references:
docker volume ls -f dangling=trueInspect any name you do not recognise, and look inside if needed:
docker run --rm -v VOLUME_NAME:/data:ro debian:12 ls -la /dataOnly when you are sure, remove unused anonymous volumes:
docker volume pruneOn current Docker versions this removes only anonymous unused volumes. Named unused volumes need docker volume prune -a, or docker volume rm NAME one at a time, which is safer.
Warning: A deleted volume cannot be recovered. Back it up first if there is any doubt.
The all-in-one command
docker system prune removes stopped containers, unused networks, dangling images and dangling build cache in one go:
docker system pruneAdd -a to also remove all unused images. It asks for confirmation and lists what it will remove. It does not touch volumes unless you add --volumes.
Schedule a safe weekly cleanup
A cron job that removes old images and build cache but never volumes:
sudo crontab -eAdd this line to run every Sunday at 04:30:
30 4 * * 0 /usr/bin/docker system prune -af --filter "until=168h" > /var/log/docker-prune.log 2>&1-f skips the confirmation prompt. The until filter keeps anything from the last week, so you can still roll back to a recent image.
Tip: If a container is stopped on purpose for a long time, its image will be removed by this job. That is fine: Docker pulls it again when you start it, as long as the tag still exists in the registry.
Check it works
Run docker system df again and compare the SIZE column, then confirm the disk itself has more free space:
docker system df
df -h /Finally, check that your apps are still up with docker ps.
Troubleshooting
- Prune freed almost nothing: the space is in container logs or in volumes. Check
/var/lib/docker/containersanddocker system df -v. - Disk still full after pruning: large files outside Docker, such as backups or system logs. Free up disk space on a Linux VPS covers the rest of the system.
overlay2folder is huge: see Fix Docker filling the disk (overlay2).- An app lost its data after a prune: its volume was pruned. Restore from your backup and avoid
--volumesin scheduled jobs.
Next steps
- Stop logs from growing back: View and rotate Docker container logs.
- Clean up the rest of the system: Free up disk space on a Linux VPS.
