RAPID INCIDENT TRIAGE & ACTION PLAN•Performance
01. Error Signature
Docker Overlay2 Build Disk Space Analyzer
02. Root Cause Vector

Docker build with --no-cache fails on overlay2 hosts at 90%+ disk usage due to unreclaimed layer debris, dangling images, and BuildKit ca...

03. Rapid Prescription

Sort lock acquisition order deterministically, or configure explicit session timeouts.

Zero-Trust Client IDE/ Performance

Docker Overlay2 Build Disk Space Analyzer

Docker build with --no-cache fails on overlay2 hosts at 90%+ disk usage due to unreclaimed layer debris, dangling images, and BuildKit cache bloat exhausting the filesystem.

SYSTEM STATUS
CREDITS: 0 / 3
source.yaml(47L)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#!/bin/bash
# TODO: This script was hastily adapted from the old Jenkins pipeline. Needs refactoring.
# WARNING: DO NOT RUN IN PRODUCTION WITHOUT REVIEW - legacy artifact handling.

# --- Legacy Registry Config (PCI Secure Zone) ---
export DOCKER_REGISTRY="my-registry.internal:5000/legacy-api"
export DOCKER_IMAGE_TAG="v2.1.3-patch-${BUILD_NUMBER:-unknown}"

# --- Synthetic Secrets (DO NOT COMMIT) ---
export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
export STRIPE_API_KEY="sk_live_4eC39HqLyjWDarjtT1zdp7dc"
export DB_CONNECTION_URI="postgresql://legacy_user:SuperSecretPass123!@pci-db.internal:5432/secure_zone?sslmode=require"

# --- Multi-line RSA Private Key (Dummy) ---
export SSH_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAtX8tJz7KkLm8N9v6X8ZqJQ7bTexamplekeydataheremoreandmore\n-----END RSA PRIVATE KEY-----"

# --- Build Configuration with Overrides ---
# VULNERABILITY: The cleanup step is conditionally skipped if the build is tagged as 'retry', but the overlay2 driver caches all intermediate layers. On a host at 90% disk usage, a no-cache rebuild will exhaust space.
if [[ "${BUILD_TAG:-}" == *"retry"* ]]; then
    echo "Retry build detected - skipping cleanup to preserve logs (temporary workaround)."
    # TODO: fix this workaround - disk fills up on retries
    CLEANUP_INTERMEDIATES="false"
else
    CLEANUP_INTERMEDIATES="true"
fi

# --- Redundant Old Config (commented out) ---
# export DOCKER_BUILD_ARGS="--compress --force-rm"
# export DOCKER_BUILD_CONTEXT="./legacy-context"

# --- Actual Build Command ---
echo "Building image ${DOCKER_REGISTRY}:${DOCKER_IMAGE_TAG}"
# NOTE: Using --no-cache to avoid layer conflicts from the old registry.
docker build --no-cache -t "${DOCKER_REGISTRY}:${DOCKER_IMAGE_TAG}" .

# --- Conditional Cleanup (often skipped) ---
if [[ "$CLEANUP_INTERMEDIATES" == "true" ]]; then
    echo "Cleaning up intermediate containers..."
    docker system prune -f
else
    echo "Skipping cleanup for diagnostic purposes."
fi

# --- Legacy Health Check (often fails) ---
# curl -k https://${DOCKER_REGISTRY}/v2/ 2>/dev/null || echo "Registry unreachable - check PCI zone firewall."
AI Audit Console
> Waiting for pre-flight audit...
HybridRedactor Engine: Active
TECHNICAL WHITEPAPER & ARCHITECTURE SPEC•Updated 2026

How to Fix 'No Space Left on Device' During Docker Build on overlay2 (90% Disk Usage)

Threat/Impact Level: HIGH | Downtime Risk: HIGH | Time to Fix: 10–30 mins


TL;DR

  • What broke: docker build --no-cache exhausted the host filesystem. overlay2 accumulates unreferenced layer tarballs, dangling images, and BuildKit's content-addressable cache in /var/lib/docker — --no-cache makes it worse by bypassing layer reuse and writing fresh layers every run.
  • How to fix it: Run docker system prune -af --volumes + purge BuildKit cache with docker builder prune -af, then reclaim /var/lib/docker/overlay2 orphans manually if needed.
  • Fast path: Use our Client-Side Sandbox above to auto-refactor your Dockerfile and CI pipeline config to prevent this from recurring.

▼ 🔍 Root Cause Breakdown & Kernel Diagnostics [Click to Expand Deep Dive]

The Incident (What Does the Error Mean?)

Raw error during docker build --no-cache -t myapp:latest .:

Step 14/22 : RUN npm ci
no space left on device
error building image: error building stage: failed to solve with frontend dockerfile.v0:
failed to read dockerfile: failed to create temp dir: no space left on device

or from BuildKit:

 => ERROR [build 7/9] RUN apt-get update && apt-get install -y build-essential
------
 > [build 7/9] RUN apt-get update && apt-get install -y build-essential:
------
executor failed running [/bin/sh -c apt-get update ...]: exit code: 1
Error: error from sender: open /proc/self/fd/...: no space left on device

Immediate consequence: The build daemon cannot allocate new overlay2 upper-dir layers. The host's root or /var/lib/docker mountpoint is at 100% capacity. Every subsequent docker command that writes to disk — including docker pull — will fail. If this is a CI runner, the agent itself may crash.


▼ 🔍 Detailed Impact & Blast Radius Analysis [Click to Expand Deep Dive]

The Attack Vector / Blast Radius

This is not a one-time spike. It is a compounding failure mode:

  1. --no-cache forces full layer rewrite on every build. Each run writes a complete new set of overlay2 layers. Without cache reuse, old intermediate layers are not referenced but are not immediately GC'd.
  2. BuildKit's content-addressable store (/var/lib/docker/buildkit/) is never automatically purged. It accumulates blobs, snapshots, and metadata across every build invocation.
  3. Dangling images (<none>:<none>) from prior failed or replaced builds consume gigabytes silently. docker images -f dangling=true routinely shows 10–40 GB on active CI hosts.
  4. Container log files under /var/lib/docker/containers/<id>/ are unbounded by default. A single chatty container can consume the remaining free space.
  5. Cascading failure: Once the disk hits 100%, containerd and dockerd themselves can crash, taking down all running containers on the host — including unrelated production workloads if this is a shared node.

On Kubernetes nodes using overlay2, this triggers DiskPressure taint, evicting pods cluster-wide.


How to Fix It

Step 1 — Diagnose First (30 seconds)

# Where is space going?
df -h /var/lib/docker
docker system df -v

# Find the biggest offenders
du -sh /var/lib/docker/overlay2
du -sh /var/lib/docker/buildkit
du -sh /var/lib/docker/containers

# Dangling images
docker images -f dangling=true --format '{{.Size}}' | sort -rh | head

Basic Fix — Emergency Reclaim

# Nuclear option — removes ALL unused images, containers, networks, volumes
docker system prune -af --volumes

# Purge BuildKit cache specifically (often 5–20 GB)
docker builder prune -af

# Truncate container logs (replace <container_id> or loop all)
truncate -s 0 /var/lib/docker/containers/*/*-json.log

# Verify
df -h /var/lib/docker

Enterprise Best Practice — Dockerfile Refactor + Daemon Config

Problem: Fat single-stage Dockerfile bloating layer count

- FROM node:20
- COPY . .
- RUN npm install
- RUN npm run build
- RUN apt-get update && apt-get install -y curl git vim

+ FROM node:20-alpine AS builder
+ WORKDIR /app
+ COPY package*.json ./
+ RUN npm ci --omit=dev
+ COPY . .
+ RUN npm run build
+
+ FROM node:20-alpine AS runtime
+ WORKDIR /app
+ COPY --from=builder /app/dist ./dist
+ COPY --from=builder /app/node_modules ./node_modules
+ # No dev tools, no source, no cache debris in final image

Problem: No log rotation or BuildKit GC limits configured in daemon.json

# /etc/docker/daemon.json
 {
-  "storage-driver": "overlay2"
+  "storage-driver": "overlay2",
+  "log-driver": "json-file",
+  "log-opts": {
+    "max-size": "10m",
+    "max-file": "3"
+  },
+  "builder": {
+    "gc": {
+      "enabled": true,
+      "defaultKeepStorage": "10GB",
+      "policy": [
+        { "keepStorage": "10GB", "filter": ["unused-for=48h"] },
+        { "keepStorage": "5GB",  "all": true }
+      ]
+    }
+  }
 }

Apply with: systemctl restart docker

Problem: CI pipeline runs --no-cache unconditionally

- docker build --no-cache -t myapp:$CI_COMMIT_SHA .

+ docker build \
+   --cache-from myapp:latest \
+   --build-arg BUILDKIT_INLINE_CACHE=1 \
+   -t myapp:$CI_COMMIT_SHA \
+   -t myapp:latest .

💡 Tired of pasting proprietary infrastructure configs into public LLMs? Generic AI interfaces log your company's ARNs, connection strings, and private keys. StackEngine enforces client-side zero-trust boundaries—the sandbox above executes 100% locally in your browser. Drop your broken manifest above to redact secrets locally and synthesize deterministic patch drafts with your own API key.

(For CI/CD pipeline automation, install via npm i -g stackengine).


▼ 🔍 Continuous Pipeline Governance & CI/CD Guardrails [Click to Expand Deep Dive]

Prevention in CI/CD

1. Add a pre-build disk check to your pipeline

# .gitlab-ci.yml / GitHub Actions equivalent
before_script:
  - |
    USAGE=$(df /var/lib/docker | awk 'NR==2 {print $5}' | tr -d '%')
    if [ "$USAGE" -gt 80 ]; then
      echo "[WARN] Docker disk at ${USAGE}%. Running prune."
      docker system prune -f
      docker builder prune -f --keep-storage 5GB
    fi

2. Enforce image size limits with a Dockerfile linter

# Hadolint — catches layer-bloating anti-patterns before they hit CI
docker run --rm -i hadolint/hadolint < Dockerfile

# Dockle — CIS benchmark + size audit
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  goodwithtech/dockle myapp:latest

3. OPA/Conftest policy — block builds without multi-stage

# policy/dockerfile.rego
package dockerfile

deny[msg] {
  input[i].Cmd == "from"
  count([s | input[s].Cmd == "from"]) == 1
  input[j].Cmd == "run"
  contains(input[j].Value[0], "apt-get install")
  msg := "Single-stage build with apt installs detected. Use multi-stage to reduce layer bloat."
}

4. Mount `/var/lib/docker` on a dedicated volume

On EC2/GCP/Azure, never let Docker share the root EBS volume. Mount a dedicated 100GB+ gp3 volume at /var/lib/docker. Set CloudWatch/Prometheus alerts at 70% and 85% utilization — not 95%.

# Alert threshold in Prometheus
- alert: DockerDiskPressure
  expr: (node_filesystem_avail_bytes{mountpoint="/var/lib/docker"} / node_filesystem_size_bytes{mountpoint="/var/lib/docker"}) < 0.20
  for: 5m
  labels:
    severity: warning
  annotations:
    summary: "Docker storage below 20% free on {{ $labels.instance }}"

Official Grounding & Normative Specifications

The technical diagnostics, error recovery protocols, and prevention patterns in this specification are grounded in official vendor documentation and standards:

Diagnostic & Architectural FAQ

Q1.Why does 'docker build --no-cache' make disk space problems worse, not better?
The '--no-cache' flag forces Docker to generate entirely new overlay2 layers for every build, bypassing cached intermediate layers. This results in a complete duplication of layer directories under /var/lib/docker/overlay2/ on each invocation. Concurrently, unreferenced layers from previous builds are not immediately purged, leading to accelerated disk exhaustion as storage is consumed by both active and orphaned data. This is a fundamental architectural inefficiency in the overlay2 driver that prioritizes build speed over storage lifecycle management.
Q2.How do I find out exactly what is consuming space inside /var/lib/docker?
You can manually run commands like 'docker system df -v' and 'du -sh' on various /var/lib/docker subdirectories to audit usage. However, this process is highly error-prone and risky. Manually interpreting this output and deciding what to delete can easily lead to accidental deletion of critical container layers, active build cache, or essential volume data, causing immediate production outages. To avoid this security vulnerability and operational blast radius, drop the broken manifest into the StackEngine Local Sandbox above to automatically compile a zero-trust fix that surgically identifies and remediates only the safe-to-delete artifacts.
Q3.Will 'docker system prune -af --volumes' delete my running container data?
While the command is designed to avoid deleting resources attached to running containers, relying on it at scale or in complex mono-repo environments is a compliance and operational nightmare. Manually executing this across hundreds of pipelines or microservices introduces inconsistent state, audit trail gaps, and risks of human error that violate security policies. For reliable, automated pull request generation with Maker-Checker review and enforceable compliance guardrails, upgrade to the StackEngine CI/CD Automator (Team Edition). It provides on-prem analysis, automated policy enforcement, and centralized logging for all container lifecycle operations.