1. Introduction

no space left on device is the error that takes down build agents, breaks deploys, and wedges databases at 2am. Docker is a frequent culprit because /var/lib/docker quietly accumulates dangling images, stopped containers, unused volumes, and — the biggest hidden offender — build cache. The disk fills, writes fail, and everything that touches the filesystem starts erroring.

This guide shows you how to find what is consuming the disk (bytes vs inodes — they fail the same way), reclaim space safely without nuking data you need, and stop it from recurring. Commands are Linux-host oriented, which covers CI runners, EC2 instances, and Kubernetes nodes.

2. What "No Space Left" Really Means

There are two independent ways a filesystem runs out: blocks (actual bytes) and inodes (the count of files). Millions of tiny files can exhaust inodes while df -h still shows free space — so always check both.

df -h            # block/byte usage per mount
df -i            # inode usage per mount  (look for IUse% at 100%)

3. Common Causes

4. Step-by-Step Diagnosis and Fix

Step 1: Measure — bytes and inodes, then where

df -h ; df -i                         # blocks and inodes
sudo du -xh /var/lib/docker --max-depth=1 | sort -rh | head

# Docker's own accounting of reclaimable space
docker system df
docker system df -v                   # per-image / per-volume / cache detail

Step 2: Reclaim the safe, obvious wins first

# Remove stopped containers, dangling images, unused networks, build cache.
# This does NOT remove named volumes or images still in use.
docker system prune

# Also drop the build cache explicitly (often the biggest chunk)
docker builder prune                  # add -a to remove ALL cache

Step 3: Prune images and containers deliberately

# Dangling images only (safe)
docker image prune

# ALL images not used by a container (aggressive — will re-pull later)
docker image prune -a

# Remove exited containers
docker container prune

# Time-box it: remove objects older than 24h
docker system prune -a --filter "until=24h"

Step 4: Handle volumes carefully (data lives here)

# List volumes and see which are dangling (not attached to a container)
docker volume ls
docker volume ls -f dangling=true

# Remove ONLY unused volumes — never blind-prune a DB volume
docker volume prune

# Inspect a volume's mountpoint/size before deleting
docker volume inspect <volume-name>

Step 5: Cap container logs (a frequent silent filler)

# Find the biggest container logs
sudo sh -c 'du -sh /var/lib/docker/containers/*/*-json.log | sort -rh | head'

# Fix globally in /etc/docker/daemon.json, then restart Docker:
{
  "log-driver": "json-file",
  "log-opts": { "max-size": "10m", "max-file": "3" }
}
# sudo systemctl restart docker  (recreate containers to apply)

Step 6: Fix inode exhaustion

# If df -i shows IUse% ~100% but df -h has space, you're out of inodes.
# Find directories with the most files:
sudo find /var/lib/docker -xdev -type f | cut -d/ -f1-6 | sort | uniq -c | sort -rh | head

# Pruning images/build cache usually frees millions of small-file inodes:
docker system prune -a
docker builder prune -a

5. Verification Steps

# Space and inodes recovered
df -h ; df -i
docker system df

# Prove writes work again
docker run --rm alpine sh -c 'dd if=/dev/zero of=/tmp/t bs=1M count=50 && echo OK'

# On a Kubernetes node, confirm DiskPressure cleared
kubectl describe node <node> | grep -i pressure

6. Common Mistakes

7. Prevention Tips

8. FAQ

df -h shows free space but I still get "no space left on device". How?

You've run out of inodes, not bytes. Run df -i and look for IUse% near 100%. This is common with build caches and node_modules layers that create millions of tiny files. Pruning images and build cache (docker system prune -a, docker builder prune -a) frees inodes back up.

What's the safest single command to reclaim Docker space?

docker system prune (without -a or --volumes). It removes stopped containers, dangling images, unused networks, and build cache, but keeps named volumes and images still referenced by containers. Add docker builder prune to clear build cache. Only reach for -a/--volumes once you've confirmed what they'll delete.

The disk keeps filling every few days even after pruning. Why?

Almost always unbounded container logs. The default json-file driver has no size limit, so a chatty container writes gigabytes over time. Set max-size/max-file in /etc/docker/daemon.json, restart Docker, and recreate containers so the limit applies.

9. Summary

SymptomCauseFix
Disk full, df -h at 100%Images/cache/containersdocker system prune + builder prune
Free bytes but writes failInode exhaustiondf -i; prune images & cache
Refills every few daysUnbounded logsSet log max-size/max-file
Volume disk growingDangling volumesdocker volume prune (carefully)
Node DiskPressure/evictionsImage/log growth on nodeTune kubelet image GC

Explore More in This Category

Explore more in this category: Container guides. Browse all DevOps Compass articles or jump to: Kubernetes, AWS, CI/CD, Containers, Monitoring, Networking.