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
-ato remove all unused images. - Careful:
--volumescan 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
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
- Docker Desktop shows the host as free. Docker runs in a fixed-size VM, so your Mac/Windows drive can have plenty of room while the VM is full. Prune inside Docker, or raise the VM's disk-image size in Settings → Resources.
- Out of inodes, not bytes. On Linux, run
df -i. Millions of tiny layer files can exhaust the inode table even with free bytes — the error is identical, and pruning images/containers frees inodes too. - A single log file ate the disk. A chatty container with the default
json-filelog driver and no size cap can grow a multi-gigabyte log. Cap it indaemon.jsonwithlog-optsmax-sizeandmax-file.
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
- ✓
docker system df— read theRECLAIMABLEcolumn to see the big consumers - ✓ Start safe:
docker system prune(data-safe without--volumes) - ✓ Old image versions dominating? Add
-a - ✓ Build cache is the biggest?
docker builder prune - ✓ Never add
--volumeswithout checkingdocker volume lsfirst - ✓ Docker Desktop? The VM disk may be full while the host is free
- ✓ Linux with free bytes but still failing? Check
df -ifor inode exhaustion
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.