Docker accumulates leftovers: old image versions after every update, stopped containers, build cache, unused volumes, and container logs. On a VPS with a modest disk, /var/lib/docker can quietly grow to fill it. Here’s how to see what’s using space and clean it up without deleting anything you need.

Step 1: see what’s using space

docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          34        9         12.4GB    9.1GB (73%)
Containers      12        9         310MB     45MB (14%)
Local Volumes   15        8         6.2GB     1.9GB (30%)
Build Cache     210       0         3.8GB     3.8GB

“Reclaimable” is what cleanup could remove. Details per item:

docker system df -v

And the full picture on disk, including logs:

sudo du -sh /var/lib/docker/*  2>/dev/null | sort -h

Step 2: remove the safe stuff

Stopped containers

docker container prune

Removes all stopped containers. Running ones are untouched. Make sure you don’t need anything inside a stopped container first (docker ps -a).

Dangling images

docker image prune

“Dangling” images are untagged layers — typically old versions left behind after docker pull or rebuilds (<none> in docker images). Always safe to remove.

All unused images

docker image prune -a

Removes every image not used by an existing container. This frees the most space. The catch: images for stacks that are currently stopped or not yet started will be downloaded again next time. Add a filter to keep recent ones:

docker image prune -a --filter "until=168h"     # older than 7 days

Build cache

docker builder prune            # dangling build cache
docker builder prune -a         # all build cache
docker buildx prune --keep-storage 2GB   # keep a budget for faster builds

On build servers and CI runners, build cache is often the biggest consumer.

Step 3: volumes — be careful

docker volume ls -f dangling=true
docker volume prune             # anonymous unused volumes
docker volume prune -a          # ALL unused volumes, including named ones

Volumes hold data — databases, uploads. A volume counts as “unused” when no container references it, which includes stacks you’ve temporarily brought down with docker compose down. Inspect the list before pruning, and back up anything that might matter. See Docker volumes.

The all-in-one command

docker system prune

Removes stopped containers, unused networks, dangling images and dangling build cache. Add flags for more:

docker system prune -a            # + all unused images
docker system prune -a --volumes  # + unused volumes (careful!)
docker system prune -f            # no confirmation prompt (for scripts)

docker system prune -a without --volumes is a good routine cleanup: it removes things that can be re-downloaded or rebuilt, never data.

Container logs

Log files don’t show up in docker system df. Find large ones:

sudo sh -c 'du -h /var/lib/docker/containers/*/*-json.log' | sort -h | tail

Truncate one:

sudo truncate -s 0 /var/lib/docker/containers/<id>/<id>-json.log

And prevent it permanently with log limits in /etc/docker/daemon.json — see Docker logs.

Automate the cleanup

A weekly cron job that keeps a week of images:

# /etc/cron.d/docker-prune
30 4 * * 0 root docker image prune -af --filter "until=168h" > /dev/null && docker builder prune -af --filter "until=168h" > /dev/null

Or a systemd timer if you prefer — see the crontab guide.

Leave volumes out of automated pruning.

Still out of space?

  • Images are big — use slim base images and multi-stage builds; see reducing Docker image size.
  • Data in containers’ writable layers — docker ps -s shows container sizes. Apps writing to their container filesystem should write to a volume instead.
  • Overlay2 leftovers after crashes — usually removed by prune; as a last resort, stop Docker and check /var/lib/docker/overlay2 with care (don’t delete folders by hand while Docker is running).
  • Docker isn’t the culprit — check the rest of the disk: disk full troubleshooting and finding large files.
  • Move Docker’s data root to a bigger disk via "data-root" in daemon.json.

Quick reference

Command Removes Risk
docker container prune Stopped containers Low
docker image prune Dangling images None
docker image prune -a Images not used by containers Re-download later
docker builder prune -a Build cache Slower next build
docker network prune Unused networks None
docker volume prune Unused anonymous volumes Data loss possible
docker system prune -a All of the above except volumes Low
docker system prune -a --volumes Everything unused Data loss possible

For a host with room to grow, our Docker VPS plans scale storage along with CPU and RAM.

  • Docker
  • Disk Space
  • Maintenance