TechEarl

docker system prune: Free Disk Space Used by Docker

Docker fills up your disk. The prune commands clean it: docker system prune for the everyday sweep, docker system prune -a --volumes for the nuclear option, docker builder prune for the BuildKit cache, plus the per-resource versions.

Ishan KarunaratneIshan Karunaratne⏱️ 7 min readUpdated
Share thisCopied

Docker fills up your disk. Pulled images stack up, exited containers stick around, stale volumes from old projects sit there forever, and BuildKit's cache grows independently of everything else. The cleanup commands are simple; the flags decide which categories of stuff get wiped and how aggressive the sweep is.

The everyday cleanup

bash
docker system prune

That removes:

  • All stopped containers.
  • All unused networks (networks with no containers attached).
  • All dangling images (untagged layers — the leftovers from rebuilding an image).
  • All build cache that isn't referenced by an in-use image.

It does not remove tagged images you have on disk but aren't currently using, and it does not touch named volumes. That's the safe default — won't delete data, will reclaim a few GB on a typical dev machine.

bash
# Skip the "are you sure?" prompt
docker system prune -f

Going further

bash
docker system prune -a

The -a flag adds all unused images to the sweep — not just dangling ones. An image is "unused" if no container is using it. If you keep many tagged images around for testing, this can free a lot of space. It also means the next time you need one of those images, Docker re-pulls it.

bash
docker system prune -a --volumes

This is the nuclear option. Adds unused named volumes to everything else. Volumes are where state lives — mysql-data, pg-data, wp-content. Use with care. Docker asks for confirmation, but past that, the data is gone.

I run docker system prune casually, docker system prune -a when I want to free more, and docker system prune -a --volumes only when I'm sure I have no important state in named volumes.

Per-resource prune commands

Sometimes you want to clean just one category:

bash
docker container prune     # stopped containers only
docker image prune         # dangling images only
docker image prune -a      # all unused images
docker volume prune        # unused volumes (data loss potential)
docker network prune       # unused networks
docker builder prune       # BuildKit cache only
docker builder prune -a    # all BuildKit cache, including used layers

docker builder prune is the one most people forget. The BuildKit cache lives separately from docker system prune's sweep until very recent Docker releases, and it can quietly grow to tens of GB on a host that does a lot of building.

Checking how much Docker is actually using

bash
docker system df

Output looks something like:

code
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          47        12        18.3GB    14.1GB (77%)
Containers      18        3         245MB     201MB (82%)
Local Volumes   34        8         8.2GB     6.1GB (74%)
Build Cache     412       0         12.4GB    12.4GB

That tells you:

  • 47 images on disk taking 18.3 GB; 14.1 GB of that is reclaimable (docker system prune -a would get it).
  • 18 containers but only 3 running; 201 MB of stopped containers (docker container prune would clean these).
  • 34 volumes, 8 of them attached to running containers; 6.1 GB of orphaned volume data.
  • Build cache: 12.4 GB, all reclaimable with docker builder prune.

Always run docker system df before pruning so you know what you're freeing. The -v (verbose) flag shows the per-item breakdown.

Docker Desktop's disk image (Mac and Windows)

On Mac and Windows, Docker Desktop runs Linux in a VM, and everything Docker stores — images, volumes, containers, BuildKit cache — lives inside a single virtual disk image on the host. The image grows but doesn't shrink automatically. So even after docker system prune -a, the host disk usage doesn't drop. The internal Docker filesystem has free space; the wrapper file is still huge.

To reclaim the host space:

  • Docker Desktop → Settings → Resources → Advanced → Disk image size — drag the slider down. Docker compacts the underlying virtual disk.
  • Or Troubleshoot → Clean / Purge data — nukes everything Docker has stored and recreates a fresh disk. Lose everything Docker had.

Linux is simpler — pruning frees disk immediately because there's no wrapper VM. Full picture in Where Are Docker's Files on a Mac?.

Filters for selective cleanup

prune supports --filter for targeted sweeps:

bash
# Remove images older than 24 hours
docker image prune -a --filter "until=24h"

# Remove images NOT marked with this label
docker image prune -a --filter "label!=keep"

# Remove stopped containers older than a week
docker container prune --filter "until=168h"

Useful in CI to keep build hosts clean: a nightly docker system prune -a --filter "until=24h" keeps a week-or-younger image cache without wiping everything.

Automating cleanup

A cron entry that runs daily:

bash
0 3 * * * /usr/bin/docker system prune -af --filter "until=168h" >> /var/log/docker-prune.log 2>&1

That runs at 3 AM, removes everything unused that's older than a week, and logs. Adjust the threshold for your build cache hit rate.

Common pitfalls

  • docker system prune -a --volumes on a database host. All named volumes that aren't currently mounted die. If you stopped your database container "just for a minute," that volume is now in the kill list.
  • Pruning while a build is running. BuildKit references its cache layers; pruning during a build can cause weird failures. Wait for builds to finish.
  • Surprised by Mac/Windows disk usage not dropping after prune. It dropped inside Docker's VM, not on your Mac. Use Docker Desktop's "Disk image size" slider to compact, or "Clean / Purge data" to reset.
  • docker builder prune clearing too much. Without -a, it leaves recent/used cache alone. With -a, every layer goes — next build is from scratch.
  • Volumes lingering after a docker compose down -v. That command removes the project's named volumes, but if you mounted external volumes (declared in docker-compose.yml as external: true), they survive. Verify with docker volume ls.

What to do next

FAQ

Sources

Authoritative references this article was fact-checked against.

TagsDockerDisk SpacePruneCleanupBuildKitDevOps

Found this useful? Pass it on.

Copied
Ishan Karunaratne

Ishan Karunaratne

Tech Architect · Software Engineer · AI/DevOps

Tech architect and software engineer with 20+ years building software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Currently Chief Technology Officer at a healthcare tech startup, which is where most of these field notes come from.

Keep reading

Related posts

H

How to Run Apache in Docker

Apache httpd in a Docker container: serve static files, mount a custom httpd.conf, enable mod_rewrite for .htaccess, and the patterns that come up most often (PHP, reverse proxy, virtual hosts).