SE
STACKENGINE
Zero-Trust Client IDE/ Performance

Docker Build Context Size Optimizer

Missing or misconfigured .dockerignore causes Docker to send gigabytes of node_modules and build artifacts as build context, triggering daemon timeouts and 'context canceled' failures.

SYSTEM STATUS
CREDITS: 0 / 3
source.yaml(1L)
AI Audit Console
> Waiting for pre-flight audit...
AirLock HYBRID KERNEL: Active
TECHNICAL WHITEPAPER & ARCHITECTURE SPECUpdated 2026

How to Fix Docker Build Context Too Large & 'context canceled' Error (node_modules Not Ignored)

Threat/Impact Level: HIGH | Downtime Risk: HIGH | Time to Fix: 5–15 mins

TL;DR

  • What broke: Docker is shipping your entire project directory — including node_modules, .git, and build artifacts — to the daemon as build context. On large projects this exceeds hundreds of MB, causing the daemon to cancel the stream mid-transfer.
  • How to fix it: Create or correct your .dockerignore to exclude node_modules, .git, dist, and any other non-essential paths before the daemon even sees them.
  • Use the Client-Side Sandbox above to drop in your Dockerfile + .dockerignore and auto-generate the corrected ignore rules and optimized layer ordering.

The Incident (What Does the Error Mean?)

You ran docker build and got something like:

Sending build context to Docker daemon  1.4GB
Step 1/12 : FROM node:20-alpine
error: context canceled

or silently:

[+] Building 0.0s (0/0) DOCKER_BUILDKIT=1
error: context canceled

Immediate consequence: The build never starts. The Docker daemon accepted a multi-hundred-MB or multi-GB tar stream from the CLI client, hit a socket timeout or memory pressure threshold, and dropped the connection. Your CI pipeline is blocked. Every retry reproduces the same failure because the root cause — the missing .dockerignore — is still present.


The Attack Vector / Blast Radius

This is a build pipeline availability failure with a secondary secret exfiltration risk.

Performance blast radius:

  • node_modules in a typical React/Node project runs 300 MB–1.5 GB. Without .dockerignore, this is tarred and streamed to the daemon on every single build invocation, even if zero JS dependencies changed.
  • In CI (GitHub Actions, GitLab CI, Jenkins), this exhausts the runner's ephemeral disk or network buffer, causing cascading job failures across the queue.
  • BuildKit cache is completely defeated — layer caching cannot help you if the context invalidation happens at the COPY . . layer because node_modules timestamps change on every npm install.

Security blast radius:

  • .env files, .aws/credentials, private keys, and local secrets sitting in the project root get baked into the image layer if COPY . . executes successfully. They are then pushed to your registry and readable by anyone with docker history <image>.
  • .git directory inclusion leaks your entire commit history — including any secrets ever committed — into the image.

How to Fix It (The Solution)

Basic Fix — Create `.dockerignore`

Place this file at the same level as your Dockerfile:

- # (no .dockerignore exists)
+ node_modules
+ npm-debug.log
+ .git
+ .gitignore
+ .env
+ .env.*
+ dist
+ build
+ coverage
+ .nyc_output
+ .DS_Store
+ *.log
+ .dockerignore
+ README.md

Verify context size immediately:

# Dry-run: measure what would be sent
docker build --no-cache . 2>&1 | head -1
# Target: "Sending build context to Docker daemon  < 10MB"

Enterprise Best Practice — Fix the Dockerfile Layer Order Too

A correct .dockerignore alone isn't enough if your Dockerfile copies everything before installing dependencies. This destroys layer cache on every source change.

  FROM node:20-alpine AS deps
  WORKDIR /app

- COPY . .
- RUN npm ci

+ # Copy dependency manifests FIRST — these layers cache until package.json changes
+ COPY package.json package-lock.json ./
+ RUN npm ci --omit=dev
+
+ # Copy application source AFTER deps are installed
+ COPY src ./src
+ COPY public ./public

  FROM node:20-alpine AS runner
  WORKDIR /app
- COPY --from=deps /app .
+ COPY --from=deps /app/node_modules ./node_modules
+ COPY --from=deps /app/src ./src
+ COPY --from=deps /app/public ./public
+ COPY package.json ./

  EXPOSE 3000
  CMD ["node", "src/index.js"]

Why this matters: With correct layer ordering, npm ci only re-runs when package.json or package-lock.json changes. Source-only changes skip straight to the COPY src layer. Build times drop from minutes to seconds.


💡 Tired of pasting proprietary configs into ChatGPT? Generic AI tools log your company's ARNs, DB strings, and private keys. StackEngine is a zero-backend, pure browser-native utility. Drop your failing config into the sandbox above. We redact your secrets locally in the browser and auto-generate the refactored code using your own API key.


Prevention in CI/CD

1. Enforce .dockerignore existence in pre-commit:

# .pre-commit-config.yaml
- repo: local
  hooks:
    - id: check-dockerignore
      name: Require .dockerignore
      entry: bash -c 'test -f .dockerignore || (echo "ERROR: .dockerignore missing" && exit 1)'
      language: system
      pass_filenames: false

2. Gate on context size in CI (GitHub Actions):

- name: Check Docker build context size
  run: |
    SIZE=$(tar -czh --exclude-from=.dockerignore . | wc -c)
    echo "Build context: $((SIZE / 1024 / 1024)) MB"
    if [ $SIZE -gt 52428800 ]; then
      echo "ERROR: Build context exceeds 50MB. Check .dockerignore."
      exit 1
    fi

3. Hadolint in CI to catch COPY . . anti-patterns:

- name: Lint Dockerfile
  uses: hadolint/[email protected]
  with:
    dockerfile: Dockerfile
    failure-threshold: warning

Hadolint rule DL3045 warns when COPY . . is used without a preceding dependency-only copy stage.

4. Checkov policy to block secret-containing files from context:

checkov -d . --check CKV_DOCKER_2,CKV_DOCKER_3

This checks that sensitive file patterns are present in .dockerignore before the image is built in your pipeline.

Further Exploration / Matrix Routing