Docker: 'No Space Left on Device' (and How to Reclaim It Safely)

Docker eats disk via dangling images, dead containers, and unbounded log files. Here is the safe order of operations instead of a blind prune.

What you'll see

Root causes

Dangling images and stopped containers

Old build layers and exited containers accumulate for months on long-lived hosts.

Unbounded container logs

The default json-file log driver has no size cap. One chatty container can write tens of GB.

Fix it

  1. See exactly what Docker is holding
    docker system df
  2. Remove dangling images and stopped containers (keeps tagged images)
    docker container prune -f && docker image prune -f
  3. Cap log growth at the daemon level
    # /etc/docker/daemon.json
    {
      "log-driver": "json-file",
      "log-opts": { "max-size": "10m", "max-file": "3" }
    }
  4. Move data-root if /var is on a small partition
    # daemon.json: "data-root": "/mnt/bigdisk/docker" then restart dockerd

Field note

Avoid docker system prune -a --volumes on a database host: it deletes every unused image AND named volumes, including the ones your data lives in. Targeted prunes are safer than the big red button.

Common questions

df on the host shows free space. Why does Docker say full?

Docker's storage lives on its own filesystem or volume — /var/lib/docker on a full partition or a full disk-backed loop device (snap/WSL installs) is full even when other mounts have space. Check df -h /var/lib/docker specifically.

Is docker system prune -a safe to run?

It removes ALL unused images (not just dangling), stopped containers, and unused networks. Running containers and their images are untouched, but image cache rebuilds get slower. On production hosts, prefer targeted pruning during a window.

Ship it right the first time

A production-shaped compose stack: healthchecks, resource limits, log rotation. Never debug a boot race again.

Docker Production Starter — $19 →

One-time. Yours to modify. Instant download from the NinjaOps template store.