Docker & DevOps

Free disk space with docker system prune

Find out how much space Docker uses with docker system df, then safely prune unused images, build cache, stopped containers and volumes, and schedule a cleanup that never touches your data.

BeginnerLinux server5 min read

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 docker commands.
  • 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:

Bash
docker system df

The 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.7GB

RECLAIMABLE is what pruning could free. For a per-item breakdown, add -v:

Bash
docker system df -v

Also compare with the whole disk, because logs are not counted in docker system df:

Bash
df -h /
sudo du -sh /var/lib/docker/containers

If the containers folder is large, the cause is container logs. Fix that with View and rotate Docker container logs.

Remove stopped containers

Bash
docker container prune

This 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:

Bash
docker image prune

To remove every image that no container uses, including tagged ones:

Bash
docker image prune -a

The 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:

Bash
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:

Bash
docker builder prune

Add -a to remove all build cache, not only dangling entries. The next build will be slower because it starts from scratch.

Remove unused networks

Bash
docker network prune

Networks 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:

Bash
docker volume ls -f dangling=true

Inspect any name you do not recognise, and look inside if needed:

Bash
docker run --rm -v VOLUME_NAME:/data:ro debian:12 ls -la /data

Only when you are sure, remove unused anonymous volumes:

Bash
docker volume prune

On 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:

Bash
docker system prune

Add -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:

Bash
sudo crontab -e

Add 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:

Bash
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/containers and docker 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.
  • overlay2 folder 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 --volumes in scheduled jobs.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.