Docker: no space left on device

Quick answer

Docker's disk (default /var/lib/docker) is full — from images, stopped containers, volumes, and build cache. Reclaim it in order:

  • See where it went: docker system df.
  • Safe cleanup: docker system prune (containers, dangling images, cache).
  • More aggressive: add -a to remove all unused images.
  • Careful: --volumes can delete database data — only if you're sure.

The exact error string

# during a pull:
write /var/lib/docker/tmp/...: no space left on device

# during a build:
failed to solve: write /var/lib/docker/...: no space left on device

# from inside a container writing a file:
Error: ENOSPC: no space left on device, write

Docker stores everything it manages under one directory — /var/lib/docker on Linux, or a fixed-size virtual disk inside the VM on Docker Desktop. That space accumulates quietly: every image you pull, every container you stop but don't remove, every volume, and every layer of build cache stays on disk until something removes it. Eventually a pull or build needs room that isn't there, and you get no space left on device — the disk counterpart to running out of memory, which surfaces as exit code 137 (OOMKilled). The fix is to see where the space went, then reclaim the parts you don't need.

Where Docker's disk actually goes

/var/lib/docker Images layers Containers writable layers Volumes your DATA Build cache intermediate docker system prune (safe) + -a : also all unused images --volumes (can delete data) only if no volume holds data you need

Four buckets fill the disk. The plain prune (green) is safe for data; --volumes (red) is the one that can wipe a database — volumes are where persistent data lives.

Step 1: see where the space went

$ docker system df
TYPE            TOTAL   ACTIVE   SIZE      RECLAIMABLE
Images          42      6        18.3GB    14.1GB (77%)
Containers      15      3        1.2GB     0.9GB (75%)
Local Volumes   9       4        6.4GB     3.1GB (48%)
Build Cache     210     0        11.8GB    11.8GB (100%)

The RECLAIMABLE column is the one to read — it shows how much of each category can be freed. Here the build cache (11.8GB, 100% reclaimable) and old images (14.1GB) are the big wins, and no volume data needs touching. Add -v to docker system df -v for a per-image and per-volume breakdown.

Before you prune anything, list the individual items so you can see exactly what's about to go — especially useful for images and volumes, where a wrong assumption is expensive:

docker image ls     # every image, its tag, and size — review before pruning
docker volume ls    # every volume — check nothing here holds data you need
docker ps -a        # all containers, including stopped ones

Step 2: reclaim safely, escalating as needed

# 1) safe: stopped containers, dangling images, unused networks, build cache
docker system prune

# 2) also remove ALL unused images (not just dangling ones)
docker system prune -a

# 3) target just the build cache — often the biggest, and always safe
docker builder prune       # removes unused (dangling) cache
docker builder prune -a    # removes ALL cache no longer needed by a build

# 4) remove only dangling images
docker image prune

Work down this list rather than jumping to the most aggressive option. The plain docker system prune is safe for your data and frees stopped containers plus dangling images plus the entire build cache — frequently enough on its own. Escalate to -a when old image versions dominate. Note the difference on the cache: docker builder prune clears only dangling cache, while docker builder prune -a also removes cache that's still referenced by previous builds but no longer needed — the bigger reclaim, and safe either way since build cache is never your data.

BuildKit: the cache that quietly eats the most

Modern Docker builds use BuildKit (the default since Docker 23), which maintains its own layer cache separate from image layers. On an active development machine — where you rebuild the same project dozens of times a day — this cache is frequently the single largest consumer of disk space, and it's the one most people forget exists because it never shows up in docker image ls. It's the Build Cache line in docker system df, and docker builder prune -a is what clears it completely. If your system df shows a surprisingly large, 100%-reclaimable Build Cache (as in the example above), that's your fastest win and there's zero risk in clearing it.

The dangerous flag: --volumes

Read before you run --volumes

docker system prune --volumes deletes every volume not currently attached to a container. A database whose container is merely stopped counts as unattached — so this command can silently wipe your Postgres or MySQL data directory. Volumes are exactly where persistent data is meant to live. Only add --volumes after confirming with docker volume ls that nothing important is unattached.

Special cases worth knowing

Step 3: keep it from filling up again

# cron/CI: reclaim without a confirmation prompt
docker system prune -f
docker builder prune -f --filter "until=168h"   # cache older than 7 days

# cap container log growth in /etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": { "max-size": "10m", "max-file": "3" }
}

Combine scheduled prunes with smaller images — multi-stage builds and -slim/-alpine base images cut image size at the source, which is the most durable way to avoid the problem returning.

Debugging checklist

Frequently Asked Questions

What causes 'no space left on device' in Docker?

Docker has run out of disk in the area it stores data (by default /var/lib/docker, or the Docker Desktop VM disk). The space is consumed by four things that accumulate over time: image layers, stopped containers and their writable layers, named and anonymous volumes, and the build cache. A pull, build, or container write then fails because there's no room left to write the new data.

How do I free up Docker disk space quickly?

Run docker system df to see what's using space, then docker system prune to remove stopped containers, unused networks, dangling images, and the build cache. Add -a to also remove all unused images (any image not attached to a running container), and --volumes only if you're sure no unused volume holds data you need. Start with the plain prune and escalate.

Is docker system prune safe? Will it delete my data?

docker system prune without --volumes is safe for your data: it removes stopped containers, dangling images, unused networks, and build cache, none of which hold persistent data. The one flag that can destroy data is --volumes — it deletes every volume not currently attached to a container, which can wipe a database volume whose container happens to be stopped. Adding -a is not a data risk: it removes all unused images, so its only cost is having to re-pull or rebuild them later. Treat --volumes as the single line you never cross without checking docker volume ls first.

What is taking up the most Docker space — images or build cache?

It varies, which is why docker system df is the first command to run — it breaks usage down into Images, Containers, Local Volumes, and Build Cache with a RECLAIMABLE column. On CI runners and active dev machines the build cache is frequently the biggest and most surprising consumer; docker builder prune clears it specifically. On servers running many versions of an image over time, old image layers usually dominate.

How do I stop Docker from filling the disk again?

Prune on a schedule (a cron job running docker system prune -f, or docker builder prune for cache), use multi-stage builds and smaller base images to shrink image size, and avoid unbounded log growth by configuring the json-file log driver with max-size and max-file in daemon.json. On Docker Desktop, you can also cap the VM's disk image size in settings and reclaim space there.

Why does the host show free space but Docker still says the disk is full?

Two common reasons. On Docker Desktop, Docker lives inside a fixed-size VM disk, so the Mac/Windows host can have plenty of free space while the VM is full — prune inside Docker or raise the VM disk limit. On Linux, you may have run out of inodes rather than bytes (df -i shows this) — millions of tiny layer files exhaust the inode table even with free bytes; pruning images and containers frees inodes too.

More Docker & backend errors

Browse the full reference for Docker, Node.js, Python, and database errors — exact message, cause, and fix.

All Error References Docker: exited with code 137 Docker: permission denied on socket
About the author

Pasindu Ishan is a software developer based in Sri Lanka. He builds privacy-first developer tools at JSON Dev Tools.