Skip to content
Latchkey

Docker "no space left on device" - Causes and Fixes

A Docker build or push dies partway through with no space left on device. The runner has simply run out of disk - almost always from accumulated image layers, build cache, and dangling volumes.

What this error means

The build fails mid-step, often while extracting a layer, writing a build artifact, or pushing an image. The error comes from the kernel, not Docker itself, so it can surface from docker build, docker pull, docker save, or a RUN step that writes a large file.

Build output
failed to register layer: Error processing tar file(exit status 1):
write /usr/lib/.../libLLVM.so.17: no space left on device

# or, during a RUN step:
ERROR: failed to solve: failed to copy: write /var/lib/docker/...: no space left on device

Common causes

Accumulated build cache and dangling layers

Each build leaves behind intermediate layers and a growing BuildKit cache. On a long-lived runner these are never garbage-collected automatically and eventually fill the disk.

Large base images and multi-stage leftovers

Pulling several large base images (CUDA, full JDKs, language toolchains) in one job can exhaust a small runner disk before the build even starts.

The runner disk is genuinely small

Default CI runners often ship with 14–30 GB of usable disk. A build that needs more transient space will fail regardless of cleanup.

How to fix it

Reclaim space immediately

Prune everything Docker is no longer using. This is safe in CI because each job starts fresh.

Terminal
docker system prune --all --force --volumes
docker builder prune --all --force

Free space before the build (GitHub Actions)

On GitHub-hosted runners, several gigabytes are taken by preinstalled toolchains you may not need. Remove them at the start of the job.

.github/workflows/build.yml
- name: Free up disk space
  run: |
    sudo rm -rf /usr/share/dotnet /opt/ghc /usr/local/lib/android
    sudo docker image prune --all --force
    df -h

Shrink what the build writes

  1. Use multi-stage builds and copy only the final artifacts into the last stage.
  2. Add a .dockerignore so large local directories (node_modules, .git, datasets) are not sent to the build context.
  3. Combine RUN steps and clean package caches in the same layer (apt-get clean && rm -rf /var/lib/apt/lists/*).

How to prevent it

  • Add a prune step at the start of every Docker job on self-hosted/long-lived runners.
  • Keep a .dockerignore checked in and current.
  • Monitor df -h in CI so you catch creeping disk usage before it fails a build.
  • Use runners with more disk for image-heavy pipelines.

Frequently asked questions

Does `docker system prune` delete my images?
With --all it removes all images not referenced by a running container, plus build cache and (with --volumes) unused volumes. In CI that is exactly what you want; on a workstation, be more selective.
Why does the disk fill up if every CI job is fresh?
It only fills up on long-lived or self-hosted runners that reuse the same disk across many jobs. Ephemeral runners start clean each time - but a single job can still exhaust a small disk.

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card