
Docker Errors Build
- 9 installs
- 9 repo stars
- Updated July 8, 2026
- openaec-foundation/docker-claude-skill-package
Helps with devops & ci/cd tasks.
About
docker-errors-build is a Claude Code skill for devops & ci/cd. It helps solo builders move faster with AI-assisted development.
- docker-errors-build
- DevOps & CI/CD
- AI-coding skill
Docker Errors Build by the numbers
- 9 all-time installs (skills.sh)
- +1 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #1,020 of 1,435 DevOps & CI/CD skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/openaec-foundation/docker-claude-skill-package --skill docker-errors-buildAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 9 |
|---|---|
| repo stars | ★ 9 |
| Last updated | July 8, 2026 |
| Repository | openaec-foundation/docker-claude-skill-package ↗ |
What it does
Helps with devops & ci/cd tasks.
Files
docker-errors-build
Quick Reference
Build Error Debugging Workflow
Build fails
|
+-- Read the FULL error message (use --progress=plain for details)
|
+-- Identify error category:
| |
| +-- "file not found" / "checksum" --> COPY/ADD path issue (see 1.1)
| +-- "context" / "sending build context" slow --> Context too large (see 1.2)
| +-- Rebuilds unexpectedly --> Cache invalidation (see 1.3)
| +-- "mount" errors --> BuildKit mount config (see 1.4)
| +-- "invalid stage" / "not found" --> Multi-stage reference (see 1.5)
| +-- "pull access denied" / "manifest unknown" --> Base image (see 1.6)
| +-- "exec format error" --> Platform mismatch (see 1.7)
| +-- Variable empty / missing --> ARG scope issue (see 1.8)
| +-- "permission denied" --> Build permission (see 1.9)
| +-- "parse error" / "unknown instruction" --> Syntax error (see 1.10)
|
+-- Apply fix from diagnostic table
|
+-- Rebuild with: docker build --progress=plain --no-cache .Critical Warnings
ALWAYS use --progress=plain when debugging build failures -- the default TTY output hides important error details.
ALWAYS check .dockerignore first when files appear missing during COPY or ADD -- this is the #1 cause of "file not found" errors.
NEVER use --no-cache as a permanent fix for cache problems -- find and fix the root cause of cache invalidation instead.
NEVER put secrets in ARG or ENV instructions -- they persist in image history. ALWAYS use RUN --mount=type=secret.
---
1. Diagnostic Tables
1.1 COPY/ADD File Not Found
| Error Message | Cause | Fix |
|---|---|---|
COPY failed: file not found in build context | File is outside the build context directory | Move file into the build context or restructure with docker build -f path/Dockerfile context/ |
COPY failed: file not found in build context | File is excluded by .dockerignore | Remove or adjust the .dockerignore pattern |
failed to compute cache key: failed to calculate checksum of ref | COPY source path does not exist relative to build context root | Verify path with ls from the build context directory. Paths are relative to context, NOT Dockerfile location |
COPY failed: no source files were specified | Glob pattern matches zero files | Check wildcard pattern. Verify files exist: ls <pattern> from context root |
ADD failed: file not found in build context | Same causes as COPY | Same fixes as COPY. ALWAYS prefer COPY over ADD for local files |
Debugging command:
# List what the builder actually sees in the context
docker build --progress=plain -f Dockerfile . 2>&1 | head -5
# Shows: "sending build context to Docker daemon X.XXkB"
# Check .dockerignore effect
cat .dockerignore1.2 Build Context Too Large
| Error Message | Cause | Fix |
|---|---|---|
sending build context to Docker daemon takes minutes | No .dockerignore or large files in context | Create .dockerignore excluding node_modules/, .git/, build artifacts |
| Context exceeds available memory | Extremely large context (multi-GB) | Use .dockerignore. Use --file with a smaller context path. Use multi-stage builds with bind mounts |
ALWAYS create a `.dockerignore` file. Without it, the ENTIRE directory tree is sent to the daemon, including node_modules/ (500MB+), .git/ (entire history), and build artifacts.
1.3 Unexpected Cache Invalidation
| Symptom | Cause | Fix |
|---|---|---|
npm install reruns on every build | COPY . . before RUN npm install | Copy package.json and lockfile FIRST, install, THEN copy source |
apt-get install gets stale packages | apt-get update in a separate RUN layer | ALWAYS combine: RUN apt-get update && apt-get install -y pkg |
| Layer rebuilds after unrelated file change | COPY instruction too broad | Copy only the files needed for each step. Order from least to most frequently changed |
| Cache never hits in CI | No cache backend configured | Use --cache-from and --cache-to with registry or GHA backend |
| RUN layer rebuilds despite identical command | Previous layer was invalidated | Check ALL preceding layers -- cache invalidation cascades downward |
1.4 BuildKit Mount Errors
| Error Message | Cause | Fix |
|---|---|---|
failed to create LLB definition: rpc error: unknown flag: --mount | Missing # syntax=docker/dockerfile:1 directive | Add # syntax=docker/dockerfile:1 as the FIRST line of the Dockerfile |
failed to create LLB definition: rpc error: unknown flag: --mount | BuildKit not enabled (pre-Engine 23) | Set DOCKER_BUILDKIT=1 or upgrade Docker Engine to 23+ |
failed to solve: failed to mount cache target | Cache directory permissions or path issue | Verify target path. Add uid and gid options if running as non-root |
error: secret "X" not found | Secret not passed to build command | Add --secret id=X,src=path to docker build command |
could not parse ssh: [default]: stat /nonexistent: no such file | SSH agent not running or key not added | Run eval $(ssh-agent) and ssh-add ~/.ssh/id_rsa before build |
inconsistent result from cache mount | Concurrent builds with sharing=shared on apt | Use sharing=locked for apt cache mounts |
1.5 Multi-Stage Reference Errors
| Error Message | Cause | Fix |
|---|---|---|
invalid from flag value X: invalid reference format | Stage name contains uppercase or invalid characters | Use lowercase alphanumeric names with hyphens only |
failed to solve: X: not found in COPY --from=X | Stage name does not exist or is misspelled | Verify the AS name in the FROM instruction matches exactly |
invalid stage index: N | Numeric --from=N references a non-existent stage | Use named stages (AS build) instead of numeric indexes |
circular dependency detected | Stage A copies from stage B which copies from A | Restructure stages to eliminate circular references |
1.6 Base Image Pull Failures
| Error Message | Cause | Fix |
|---|---|---|
pull access denied for X, repository does not exist | Image name misspelled or does not exist | Verify image name on Docker Hub or registry. Check for typos |
manifest unknown: manifest unknown | Tag does not exist for this image | Verify tag with docker manifest inspect image:tag |
unauthorized: authentication required | Private registry requires login | Run docker login <registry> before building |
error pulling image configuration: download failed after attempts | Network issue or registry timeout | Check network connectivity. Retry. Use --pull to force fresh pull |
toomanyrequests: You have reached your pull rate limit | Docker Hub rate limit exceeded | Authenticate with docker login (free accounts get higher limits). Use a registry mirror |
1.7 Platform Mismatch
| Error Message | Cause | Fix |
|---|---|---|
exec format error | Image built for wrong CPU architecture | Add --platform linux/amd64 (or target arch) to build command |
image with reference X does not match the specified platform | Pulled image has no manifest for requested platform | Check available platforms: docker manifest inspect image:tag. Build for available platform |
no match for platform in manifest list | Multi-platform image lacks requested platform | Use a different base image that supports your platform |
1.8 ARG Scope Issues
| Symptom | Cause | Fix |
|---|---|---|
| ARG value is empty inside build stage | ARG declared before FROM but not re-declared after | Re-declare ARG varname (without default) after each FROM that needs it |
| ARG value not available at runtime | ARG is build-time only, not persisted | Convert to ENV: ARG VAR then ENV VAR=$VAR if needed at runtime |
| Variable expansion not working in RUN | Using exec form RUN ["echo", "$VAR"] | Exec form does NOT expand variables. Use shell form: RUN echo $VAR |
| ENV set incorrectly using prior ENV value | Same-line ENV precedence | ENV a=bye b=$a uses a's value from BEFORE this line. Split into separate ENV instructions if needed |
1.9 Permission Errors During Build
| Error Message | Cause | Fix |
|---|---|---|
permission denied in RUN instruction | Running as non-root USER before installing packages | Place package installation BEFORE the USER instruction |
EACCES: permission denied writing to directory | Directory owned by root, running as non-root | Add RUN chown -R user:group /dir BEFORE switching to USER |
permission denied on COPY'd script | Script lacks execute permission | Add COPY --chmod=755 script.sh /app/ or RUN chmod +x /app/script.sh |
open /var/lib/apt/lists/lock: permission denied | Running apt as non-root user | Run apt commands BEFORE USER instruction, or use --mount=type=cache with correct uid/gid |
1.10 Dockerfile Syntax Errors
| Error Message | Cause | Fix |
|---|---|---|
failed to solve: dockerfile parse error on line X: unknown instruction: XXX | Misspelled instruction or wrong case | Instructions MUST be uppercase: RUN, COPY, FROM, not run, copy, from |
failed to solve: dockerfile parse error: missing FROM | No FROM instruction or FROM not first | FROM MUST be the first instruction (after parser directives and ARG) |
| Unexpected behavior with multi-line RUN | Missing \ continuation character | End each continued line with \. NEVER leave trailing spaces after \ |
failed to process "Dockerfile": no parser directive, file is empty | BOM character or wrong encoding | Save Dockerfile as UTF-8 without BOM. Remove invisible characters |
COPY requires at least two arguments | Missing destination argument | COPY needs <src> <dest>. Add trailing / for directories: COPY files/ /app/ |
---
2. Decision Trees
Which Cache Strategy to Use
Problem: Build is slow
|
+-- Dependencies reinstall every time?
| YES --> Reorder: copy lockfile first, install, then copy source
|
+-- Package downloads repeat?
| YES --> Add --mount=type=cache for your package manager
|
+-- CI builds have no cache?
| YES --> Configure --cache-from/--cache-to with registry backend
|
+-- Base image pulls every time?
| YES --> Pin base image digest. Use --cache-from=type=registry
|
+-- Entire Dockerfile rebuilds?
YES --> Check if early layer changed. Order: system deps > app deps > sourceWhen to Use --no-cache vs --no-cache-filter
Need to force rebuild?
|
+-- Entire image from scratch?
| --> docker build --no-cache .
|
+-- Only specific stage?
| --> docker build --no-cache-filter=<stage-name> .
|
+-- Fresh base image only?
| --> docker build --pull .
|
+-- Everything fresh (CI release build)?
--> docker build --pull --no-cache .---
3. Essential Debug Commands
# Full build output (ALWAYS use this when debugging)
docker build --progress=plain .
# Build specific stage only
docker build --target <stage-name> .
# Check what the build context contains
tar -czf - -C <context-dir> . | wc -c
# Inspect build cache usage
docker system df
docker builder prune --filter type=regular
docker builder prune -a # Remove ALL build cache
# Check image layers and sizes
docker history <image>
docker history --no-trunc <image>
# Verify platform of an image
docker inspect --format='{{.Os}}/{{.Architecture}}' <image>
# Check .dockerignore is working
# (compare context size with and without .dockerignore)---
Reference Links
- references/diagnostics.md -- Complete error message to cause to solution mapping with exact error strings
- references/examples.md -- Error reproduction and fix examples with before/after Dockerfiles
- references/anti-patterns.md -- Build configuration mistakes that cause errors
Official Sources
- https://docs.docker.com/build/building/best-practices/
- https://docs.docker.com/build/cache/
- https://docs.docker.com/build/cache/invalidation/
- https://docs.docker.com/reference/dockerfile/
- https://docs.docker.com/build/buildkit/
- https://docs.docker.com/engine/daemon/troubleshoot/
docker-errors-build: Build Configuration Anti-Patterns
Overview
This reference documents build configuration mistakes that cause errors, slow builds, or security vulnerabilities. Each anti-pattern includes the problem, why it fails, and the correct approach.
---
1. No .dockerignore File
Problem:
# No .dockerignore exists
docker build .
# "Sending build context to Docker daemon 1.2GB"Why it fails: Without .dockerignore, Docker sends the ENTIRE directory tree to the daemon. This includes node_modules/ (500MB+), .git/ (full history), IDE configs, test data, and secrets like .env files.
Consequences:
- Build takes minutes just to transfer context
- COPY instructions may accidentally include sensitive files
- Build cache invalidated by irrelevant file changes
Fix: ALWAYS create a .dockerignore file:
.git
node_modules
dist
build
*.log
.env
.env.*
.vscode
.idea
__pycache__
*.pyc
.DS_Store
Thumbs.db---
2. COPY . . Before Dependency Installation
Problem:
FROM node:20-alpine
WORKDIR /app
COPY . .
RUN npm ci
CMD ["node", "server.js"]Why it fails: ANY file change (even editing a comment) invalidates the COPY . . layer, which cascades to invalidate npm ci. Dependencies are reinstalled on EVERY build.
Fix:
FROM node:20-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
CMD ["node", "server.js"]Rule: ALWAYS copy dependency manifests first, install dependencies, THEN copy source code.
---
3. Separating apt-get update and install
Problem:
RUN apt-get update
RUN apt-get install -y curlWhy it fails: The apt-get update layer gets cached. When you later add packages, Docker uses the cached (stale) package index. Installation may fail with "Unable to locate package" or install outdated versions with known vulnerabilities.
Fix:
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
&& rm -rf /var/lib/apt/lists/*Rule: ALWAYS combine apt-get update with apt-get install in a SINGLE RUN instruction.
---
4. Not Cleaning Package Manager Cache
Problem:
RUN apt-get update && apt-get install -y curl git wgetWhy it fails: The apt cache (/var/lib/apt/lists/) remains in the layer, adding 30-100MB of unnecessary data to every image.
Fix:
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
git \
wget \
&& rm -rf /var/lib/apt/lists/*For Alpine:
RUN apk add --no-cache curl git wgetThe --no-cache flag for apk avoids storing the index locally.
---
5. Using latest Tag for Base Images
Problem:
FROM node:latestWhy it fails: latest is a moving target. The same Dockerfile produces different images on different days. Builds are non-reproducible, and a base image update can silently break your application.
Fix:
# Good: Pin major.minor version
FROM node:20.11-bookworm-slim
# Best: Pin to digest for full reproducibility
FROM node:20.11-bookworm-slim@sha256:abc123...Rule: NEVER use :latest in production Dockerfiles. ALWAYS pin to a specific version.
---
6. Secrets in ENV or ARG
Problem:
ENV API_KEY=sk-1234567890abcdef
ARG DATABASE_PASSWORD=supersecret
RUN connect-to-db --password=$DATABASE_PASSWORDWhy it fails:
- ENV values persist in the final image, visible via
docker inspect - ARG values appear in
docker history - Both are stored in image layers and can be extracted
Fix:
# syntax=docker/dockerfile:1
FROM alpine:3.21
RUN --mount=type=secret,id=api_key,env=API_KEY \
--mount=type=secret,id=db_pass,env=DATABASE_PASSWORD \
connect-to-db --password=$DATABASE_PASSWORDdocker build \
--secret id=api_key,src=./api_key.txt \
--secret id=db_pass,src=./db_pass.txt .Rule: NEVER use ENV or ARG for secrets. ALWAYS use --mount=type=secret.
---
7. Running as Root
Problem:
FROM node:20
WORKDIR /app
COPY . .
RUN npm ci
CMD ["node", "server.js"]Why it fails: Container runs as root by default. If the application is compromised, the attacker has root privileges inside the container, which can facilitate container escape attacks.
Fix:
FROM node:20
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY --chown=node:node . .
USER node
CMD ["node", "server.js"]Rule: ALWAYS switch to a non-root USER before CMD/ENTRYPOINT.
---
8. Using ADD When COPY Suffices
Problem:
ADD config.json /app/config.json
ADD src/ /app/src/Why it fails: ADD has implicit behaviors that COPY does not:
- Auto-extracts tar archives (may unpack unexpectedly)
- Can download URLs (unexpected network calls)
- Less predictable than COPY
Fix:
COPY config.json /app/config.json
COPY src/ /app/src/Rule: ALWAYS use COPY for local files. Use ADD ONLY when you specifically need tar extraction, URL download, or Git clone.
---
9. Too Many Layers
Problem:
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -y git
RUN apt-get install -y nginx
RUN rm -rf /var/lib/apt/lists/*Why it fails:
- Each RUN creates a separate layer
- The
rmin the last layer does NOT reduce image size -- files are still in earlier layers - More layers means larger images and slower pulls
Fix:
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
git \
nginx \
&& rm -rf /var/lib/apt/lists/*Rule: Combine related operations (especially install + cleanup) into a SINGLE RUN layer.
---
10. Shell Form ENTRYPOINT
Problem:
ENTRYPOINT /usr/bin/myapp --config /etc/app.confWhy it fails: Shell form wraps the command in /bin/sh -c, making the shell PID 1 instead of the application. Consequences:
docker stopsends SIGTERM to the shell, not the app- Application does not shut down gracefully
- Zombie processes can accumulate
Fix:
ENTRYPOINT ["/usr/bin/myapp", "--config", "/etc/app.conf"]For entrypoint scripts: End with exec "$@" to replace the shell process:
#!/bin/sh
set -e
# setup logic here
exec "$@"Rule: ALWAYS use exec form ["executable", "args"] for ENTRYPOINT.
---
11. Using cd Instead of WORKDIR
Problem:
RUN cd /app && npm install
RUN cd /app && npm buildWhy it fails: cd only affects the current RUN layer's shell. The next RUN starts from / again. Each cd must be repeated, which is fragile and error-prone.
Fix:
WORKDIR /app
RUN npm install
RUN npm buildRule: ALWAYS use WORKDIR to set the working directory. NEVER use cd in RUN.
---
12. Not Using Multi-Stage Builds
Problem:
FROM golang:1.22
WORKDIR /src
COPY . .
RUN go build -o /app
CMD ["/app"]Why it fails: The final image includes the entire Go toolchain (~800MB), source code, and build artifacts. The actual binary is only a few MB.
Fix:
FROM golang:1.22 AS build
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 go build -o /app
FROM alpine:3.21
COPY --from=build /app /usr/bin/app
USER nobody:nobody
CMD ["/usr/bin/app"]Result: Image drops from ~800MB to ~10MB.
Rule: ALWAYS use multi-stage builds for compiled languages. Separate build tools from runtime.
---
13. Ignoring .dockerignore for Secrets
Problem:
# .dockerignore does NOT exclude:
.env
.env.local
credentials.json
*.pemWhy it fails: Without explicit exclusion, COPY . . includes secrets in the image. Even if they are later deleted, they persist in earlier layers and can be extracted.
Fix:
# .dockerignore must include:
.env
.env.*
*.pem
*.key
credentials.json
secrets/Rule: ALWAYS exclude secret files in .dockerignore. NEVER rely on deleting secrets in a later layer.
---
14. Not Pinning Package Versions
Problem:
RUN apt-get update && apt-get install -y curl git
RUN pip install flask requestsWhy it fails: Package versions change over time. The same Dockerfile may install different versions on different days, leading to:
- Non-reproducible builds
- Unexpected breaking changes
- Security audit difficulty
Fix:
RUN apt-get update && apt-get install -y --no-install-recommends \
curl=7.88.1-10+deb12u5 \
git=1:2.39.2-1.1 \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txtrequirements.txt:
flask==3.0.2
requests==2.31.0Rule: ALWAYS pin package versions in production Dockerfiles. Use lockfiles (package-lock.json, poetry.lock, go.sum) where available.
---
15. Missing Syntax Directive for BuildKit Features
Problem:
FROM python:3.12-slim
RUN --mount=type=cache,target=/root/.cache/pip pip install flaskWhy it fails: Without # syntax=docker/dockerfile:1, the builder does not recognize --mount and other BuildKit extensions.
Fix:
# syntax=docker/dockerfile:1
FROM python:3.12-slim
RUN --mount=type=cache,target=/root/.cache/pip pip install flaskRule: ALWAYS include # syntax=docker/dockerfile:1 as the FIRST line when using ANY BuildKit feature (--mount, --chmod on COPY, --link, heredocs).
---
16. Numeric Stage References
Problem:
FROM golang:1.22
WORKDIR /src
COPY . .
RUN go build -o /app
FROM alpine:3.21
COPY --from=0 /app /usr/bin/appWhy it fails: Numeric references (--from=0) break when stages are added, removed, or reordered. This is fragile and hard to maintain.
Fix:
FROM golang:1.22 AS build
WORKDIR /src
COPY . .
RUN go build -o /app
FROM alpine:3.21
COPY --from=build /app /usr/bin/appRule: ALWAYS name stages with AS. NEVER use numeric indexes in --from.
---
17. ENV for Build-Only Variables
Problem:
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*Why it fails: DEBIAN_FRONTEND=noninteractive persists in the final image as an environment variable, which can cause unexpected behavior for interactive tools run inside the container.
Fix:
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*Or inline:
RUN DEBIAN_FRONTEND=noninteractive apt-get update && \
apt-get install -y curl && \
rm -rf /var/lib/apt/lists/*Rule: Use ARG or inline variables for build-only values. ONLY use ENV for variables needed at container runtime.
---
Summary Table
| # | Anti-Pattern | Primary Consequence | Severity |
|---|---|---|---|
| 1 | No .dockerignore | Slow builds, secret leaks | High |
| 2 | COPY . . before deps | Full rebuild on every change | High |
| 3 | Separate apt update/install | Stale/broken packages | High |
| 4 | No cache cleanup | Bloated images (+30-100MB) | Medium |
| 5 | Using :latest tag | Non-reproducible builds | High |
| 6 | Secrets in ENV/ARG | Credential exposure | Critical |
| 7 | Running as root | Container escape risk | High |
| 8 | ADD instead of COPY | Unpredictable behavior | Low |
| 9 | Too many layers | Bloated images | Medium |
| 10 | Shell form ENTRYPOINT | Signal handling broken | High |
| 11 | cd instead of WORKDIR | Fragile, error-prone | Low |
| 12 | No multi-stage builds | Bloated images (+hundreds MB) | High |
| 13 | Secrets not in .dockerignore | Credential exposure | Critical |
| 14 | Unpinned package versions | Non-reproducible builds | Medium |
| 15 | Missing syntax directive | BuildKit features fail | Medium |
| 16 | Numeric stage references | Fragile multi-stage builds | Low |
| 17 | ENV for build-only vars | Variable pollution in image | Low |
docker-errors-build: Complete Diagnostics Reference
Error Message Index
This reference provides an exhaustive mapping from exact Docker build error messages to their root causes and solutions. Organized by error category.
---
1. COPY/ADD File Resolution Errors
Error: COPY failed: file not found in build context
Exact output:
------
> [stage 3/5] COPY config.json /app/:
------
ERROR: failed to solve: failed to compute cache key: failed to calculate checksum of ref
moby::randomhash: "/config.json": not foundPossible causes (check in order):
1. File is outside the build context directory
- The build context is the directory passed to
docker build. Files above or outside it are NEVER accessible. - Fix: Move the file into the context, or change the context path:
# If Dockerfile is in ./docker/ but files are in ./
docker build -f docker/Dockerfile .2. File is excluded by `.dockerignore`
- Check
.dockerignorefor patterns matching the file. - Fix: Remove or adjust the pattern. Add an exception:
*.json
!config.json3. Path is wrong relative to build context
- COPY paths are relative to the build context root, NOT the Dockerfile location.
- Fix: Use
lsfrom the context directory to verify the file exists at the expected relative path.
4. Case sensitivity mismatch (Linux builds)
- Linux filesystems are case-sensitive.
Config.jsonandconfig.jsonare different files. - Fix: Match the exact case in the COPY instruction.
Error: failed to compute cache key: failed to calculate checksum of ref
Exact output:
ERROR: failed to solve: failed to compute cache key: failed to calculate checksum of ref
"randomhash::src/app": "/src/app": not foundCause: The source path in COPY or ADD does not exist in the build context.
Diagnostic steps:
# 1. Check what files are in the build context
ls -la <context-directory>/src/app
# 2. Check .dockerignore
cat .dockerignore | grep -i "src"
# 3. Rebuild with verbose output
docker build --progress=plain . 2>&1 | head -20Error: COPY requires at least two arguments
Cause: Missing destination path or malformed COPY instruction.
Common triggers:
# BAD: Missing destination
COPY package.json
# GOOD: Include destination
COPY package.json .
COPY package.json /app/Error: When using COPY with more than one source file, the destination must be a directory and end with /
Cause: Multiple source files but destination lacks trailing slash.
Fix:
# BAD
COPY file1.txt file2.txt /app
# GOOD
COPY file1.txt file2.txt /app/---
2. Build Context Errors
Symptom: sending build context to Docker daemon takes >30 seconds
Diagnostic:
# Check context size
du -sh --exclude=.git .
# Check what .dockerignore excludes
# (no built-in Docker command -- compare manually)
tar -czf /dev/null -C <context> . 2>&1Root causes and fixes:
| Size indicator | Likely culprit | Fix |
|---|---|---|
| >500 MB | node_modules/ included | Add node_modules to .dockerignore |
| >100 MB | .git/ included | Add .git to .dockerignore |
| >50 MB | Build artifacts (dist/, build/) | Add build output dirs to .dockerignore |
| Variable | Large data files, logs, media | Add *.log, *.mp4, data dirs to .dockerignore |
Minimal `.dockerignore` template:
.git
node_modules
dist
build
*.log
.env
.env.*---
3. Cache Invalidation Errors
Symptom: Dependencies reinstall on every build
Diagnostic:
# Check layer cache hits
docker build --progress=plain . 2>&1 | grep -E "CACHED|RUN"Root cause: Source code COPY before dependency installation.
Fix pattern (Node.js):
# WRONG ORDER -- any file change invalidates npm install
COPY . .
RUN npm ci
# CORRECT ORDER -- only package.json changes trigger npm install
COPY package.json package-lock.json ./
RUN npm ci
COPY . .Fix pattern (Python):
# WRONG ORDER
COPY . .
RUN pip install -r requirements.txt
# CORRECT ORDER
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .Fix pattern (Go):
# WRONG ORDER
COPY . .
RUN go build -o /app
# CORRECT ORDER
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o /appSymptom: apt-get install installs stale or missing packages
Root cause: apt-get update and apt-get install in separate RUN layers.
# BAD: apt-get update layer is cached, install uses stale package list
RUN apt-get update
RUN apt-get install -y curl nginx
# GOOD: Combined in single layer
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
nginx \
&& rm -rf /var/lib/apt/lists/*Symptom: RUN layer rebuilds despite identical command
Cause: A preceding layer was invalidated, causing ALL subsequent layers to rebuild.
Diagnostic: Run with --progress=plain and look for the FIRST non-CACHED layer. That is where invalidation started.
---
4. BuildKit-Specific Errors
Error: failed to create LLB definition: rpc error: unknown flag: --mount
Causes (check in order):
1. Missing syntax directive:
# MUST be the very first line
# syntax=docker/dockerfile:12. BuildKit not enabled (Docker Engine < 23):
DOCKER_BUILDKIT=1 docker build .3. Using legacy builder explicitly:
# If DOCKER_BUILDKIT=0 is set, unset it
unset DOCKER_BUILDKITError: error: secret "X" not found
Cause: Build command does not pass the required secret.
Fix:
# Must pass --secret flag
docker build --secret id=X,src=./secret-file.txt .
# For environment variable secrets
SECRET_VALUE=mytoken docker build --secret id=SECRET_VALUE .Error: could not parse ssh: [default]: stat /path: no such file or directory
Cause: SSH agent not running or key not loaded.
Fix:
eval $(ssh-agent)
ssh-add ~/.ssh/id_rsa
docker build --ssh default .Error: Cache mount produces inconsistent results with apt
Cause: Multiple concurrent builds writing to the same apt cache.
Fix: Use sharing=locked for apt cache mounts:
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && apt-get install -y --no-install-recommends curl---
5. Multi-Stage Build Errors
Error: invalid from flag value "Build": invalid reference format
Cause: Stage name contains uppercase letters.
Fix: Stage names MUST be lowercase:
# BAD
FROM golang:1.22 AS Build
# GOOD
FROM golang:1.22 AS buildError: failed to solve: <stage>: not found
Possible causes:
1. Stage name misspelled in COPY --from=:
FROM golang:1.22 AS builder
# ...
COPY --from=buider /app /app # TYPO: "buider" instead of "builder"2. Stage defined AFTER the COPY that references it:
- Stages MUST be defined before they are referenced (order matters).
3. --target flag skips the stage:
- When using
--target, only the target stage and its dependencies are built.
Error: circular dependency detected
Cause: Stage A copies from stage B, and stage B copies from stage A.
Fix: Restructure to break the cycle. Introduce an intermediate stage:
FROM alpine AS shared-base
COPY shared-files /shared/
FROM shared-base AS stage-a
# ...
FROM shared-base AS stage-b
COPY --from=stage-a /output /input---
6. Base Image Pull Errors
Error: pull access denied for X, repository does not exist
Diagnostic:
# Verify the image exists
docker manifest inspect <image>:<tag>
# Check for typos in common images
# nginx vs ngnix, postgres vs postgresql, python vs pythoonCauses: 1. Image name misspelled 2. Private image without authentication 3. Image genuinely does not exist
Error: manifest unknown: manifest unknown
Cause: The specified tag does not exist for this image.
Fix:
# Check available tags
docker manifest inspect <image>:<tag>
# Common mistake: using OS-specific tags that don't exist
# e.g., node:20-alpine3.19 when only node:20-alpine existsError: toomanyrequests: You have reached your pull rate limit
Docker Hub rate limits:
- Anonymous: 100 pulls per 6 hours
- Authenticated (free): 200 pulls per 6 hours
- Paid: Higher limits
Fix:
# Authenticate to increase limits
docker login
# Use a registry mirror
# In /etc/docker/daemon.json:
# { "registry-mirrors": ["https://mirror.example.com"] }---
7. Platform Mismatch Errors
Error: exec format error
Full output:
standard_init_linux.go:228: exec user process caused: exec format errorCause: Binary in the image was compiled for a different CPU architecture.
Diagnostic:
# Check image platform
docker inspect --format='{{.Os}}/{{.Architecture}}' <image>
# Check host platform
uname -mFix:
# Build for specific platform
docker build --platform linux/amd64 .
# Run with platform emulation
docker run --platform linux/amd64 <image>Error: image with reference X does not match the specified platform
Cause: Pulled image manifest does not include the requested platform.
Fix:
# Check available platforms
docker manifest inspect <image>:<tag> | grep -A2 '"platform"'
# Use a different base image version that supports your platform---
8. ARG/ENV Scope Errors
Symptom: ARG value is empty after FROM
Root cause: ARG scope resets at each FROM instruction.
# BAD: VERSION is empty in the build stage
ARG VERSION=1.0
FROM alpine:3.21
RUN echo $VERSION > /version # Empty!
# GOOD: Re-declare ARG after FROM
ARG VERSION=1.0
FROM alpine:3.21
ARG VERSION
RUN echo $VERSION > /version # "1.0"Symptom: Variable not expanded in exec form
Root cause: Exec form does NOT invoke a shell, so no variable expansion occurs.
# BAD: Literal "$HOME" string, not expanded
RUN ["echo", "$HOME"]
# GOOD: Shell form expands variables
RUN echo $HOME
# GOOD: Explicit shell in exec form
RUN ["/bin/sh", "-c", "echo $HOME"]Symptom: ARG not available at container runtime
Root cause: ARG is build-time only. It does NOT persist in the image.
# BAD: APP_VERSION not available at runtime
ARG APP_VERSION=1.0
CMD echo $APP_VERSION # Empty at runtime
# GOOD: Convert ARG to ENV for runtime persistence
ARG APP_VERSION=1.0
ENV APP_VERSION=$APP_VERSION
CMD echo $APP_VERSION # "1.0" at runtime---
9. Permission Errors During Build
Error: EACCES: permission denied, mkdir '/app/node_modules'
Cause: USER instruction set before directory creation or package install.
Fix:
# BAD: Non-root user can't write to /app
USER node
WORKDIR /app
RUN npm install # Permission denied
# GOOD: Install as root, then switch user
WORKDIR /app
COPY --chown=node:node package*.json ./
RUN npm install
USER nodeError: permission denied executing a COPY'd script
Cause: COPY preserves source file permissions. If source lacks +x, so does the copy.
Fix:
# Option 1: Set permissions in COPY (BuildKit)
COPY --chmod=755 entrypoint.sh /app/
# Option 2: chmod after COPY
COPY entrypoint.sh /app/
RUN chmod +x /app/entrypoint.shError: open /var/lib/apt/lists/lock: permission denied
Cause: Running apt as non-root user.
Fix: Run ALL system package installation BEFORE the USER instruction:
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
RUN useradd -r -s /bin/false appuser
USER appuser---
10. Dockerfile Syntax Errors
Error: unknown instruction: XXX
Cause: Instruction misspelled or in wrong case.
Common mistakes:
run echo hello # BAD: lowercase
FORM ubuntu:22.04 # BAD: typo (FORM instead of FROM)
COPY. /app/ # BAD: missing space after COPYFix: ALL Dockerfile instructions MUST be uppercase. Check spelling.
Error: Dockerfile parse error: missing FROM
Causes: 1. No FROM instruction in the Dockerfile 2. Parser directive or comment is malformed, consuming the FROM line 3. BOM character at file start
Fix: Ensure FROM is present and is the first instruction (after optional parser directives and global ARGs).
Error: Unexpected behavior with line continuations
Cause: Trailing whitespace after the \ continuation character.
# BAD: Invisible space after backslash breaks continuation
RUN apt-get update && \
apt-get install -y curl
# GOOD: No trailing whitespace after backslash
RUN apt-get update && \
apt-get install -y curlDetection: Use an editor that shows trailing whitespace, or run:
grep -nP '\\\s+$' DockerfileError: failed to process "Dockerfile": file is empty
Causes: 1. Dockerfile is actually empty 2. BOM (Byte Order Mark) character at file start 3. Wrong file encoding
Fix:
# Check for BOM
file Dockerfile
# Should show "ASCII text" or "UTF-8 Unicode text"
# If it shows "UTF-8 Unicode (with BOM) text", remove BOM:
sed -i '1s/^\xEF\xBB\xBF//' Dockerfiledocker-errors-build: Error Reproduction and Fix Examples
1. COPY File Not Found -- .dockerignore Conflict
Reproducing the Error
Project structure:
myapp/
src/
app.js
config.json
Dockerfile
.dockerignore.dockerignore:
*.jsonDockerfile:
FROM node:20-alpine
WORKDIR /app
COPY config.json .
COPY src/ ./src/
CMD ["node", "src/app.js"]Error:
ERROR: failed to solve: failed to compute cache key: failed to calculate checksum
of ref moby::randomhash: "/config.json": not foundFix
.dockerignore (corrected):
*.json
!config.json
!package.json
!package-lock.jsonThe ! prefix creates an exception to the exclusion pattern.
---
2. COPY File Not Found -- Wrong Build Context
Reproducing the Error
Project structure:
project/
docker/
Dockerfile
src/
app.py
requirements.txtBuild command (wrong):
cd project/docker
docker build .Dockerfile:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY src/ ./src/
CMD ["python", "src/app.py"]Error:
ERROR: failed to solve: failed to compute cache key: "/requirements.txt": not foundFix
Build command (correct):
cd project
docker build -f docker/Dockerfile .The build context is . (project root), while the Dockerfile is at docker/Dockerfile. COPY paths are ALWAYS relative to the build context, not the Dockerfile.
---
3. Cache Invalidation -- Wrong Layer Order
Reproducing the Error
Dockerfile (inefficient):
FROM node:20-alpine
WORKDIR /app
COPY . .
RUN npm ci --production
CMD ["node", "server.js"]Symptom: Every change to ANY file (even a comment in server.js) triggers a full npm ci, downloading all dependencies from scratch.
Fix
Dockerfile (optimized):
FROM node:20-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --production
COPY . .
CMD ["node", "server.js"]Why it works: package.json and package-lock.json change infrequently. By copying them first and running npm ci, the dependency layer is cached. Source code changes (the second COPY . .) only invalidate layers below the second COPY.
---
4. Stale apt Packages -- Separated update and install
Reproducing the Error
Dockerfile (broken):
FROM ubuntu:22.04
RUN apt-get update
RUN apt-get install -y curl
# Later addition:
RUN apt-get install -y nginxSymptom: After initial build succeeds, adding nginx later may fail with:
E: Unable to locate package nginxCause: The apt-get update layer is cached. The package index is stale.
Fix
Dockerfile (correct):
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
nginx \
&& rm -rf /var/lib/apt/lists/*Rules:
- ALWAYS combine
apt-get updateandapt-get installin a single RUN - ALWAYS use
--no-install-recommendsto avoid unnecessary packages - ALWAYS clean up with
rm -rf /var/lib/apt/lists/*
---
5. BuildKit Mount Error -- Missing Syntax Directive
Reproducing the Error
Dockerfile (broken):
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN --mount=type=cache,target=/root/.cache/pip \
pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]Error:
ERROR: failed to create LLB definition: rpc error: code = Unknown
desc = unknown flag: --mountFix
Dockerfile (correct):
# syntax=docker/dockerfile:1
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN --mount=type=cache,target=/root/.cache/pip \
pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]The # syntax=docker/dockerfile:1 directive MUST be the FIRST line. It enables BuildKit-specific features including --mount.
---
6. Secret Not Found -- Missing Build Flag
Reproducing the Error
Dockerfile:
# syntax=docker/dockerfile:1
FROM alpine:3.21
RUN --mount=type=secret,id=api_key \
cat /run/secrets/api_key > /dev/nullBuild command (wrong):
docker build .Error:
ERROR: failed to solve: could not find secret "api_key"Fix
Build command (correct):
docker build --secret id=api_key,src=./api_key.txt .For environment variable secrets:
export API_KEY=my-secret-value
docker build --secret id=API_KEY .Dockerfile for env var approach:
# syntax=docker/dockerfile:1
FROM alpine:3.21
RUN --mount=type=secret,id=API_KEY,env=API_KEY \
echo "Secret is available as $API_KEY"---
7. Multi-Stage Reference Error -- Case Sensitivity
Reproducing the Error
Dockerfile (broken):
FROM golang:1.22 AS Builder
WORKDIR /src
COPY . .
RUN go build -o /app
FROM alpine:3.21
COPY --from=Builder /app /usr/bin/app
CMD ["/usr/bin/app"]Error:
ERROR: failed to solve: invalid from flag value "Builder": invalid reference formatFix
Dockerfile (correct):
FROM golang:1.22 AS builder
WORKDIR /src
COPY . .
RUN go build -o /app
FROM alpine:3.21
COPY --from=builder /app /usr/bin/app
CMD ["/usr/bin/app"]Stage names MUST be lowercase. Use only lowercase letters, digits, and hyphens.
---
8. ARG Scope Reset After FROM
Reproducing the Error
Dockerfile (broken):
ARG APP_VERSION=1.0.0
FROM alpine:3.21
RUN echo "Version: $APP_VERSION" > /versionResult: /version contains Version: (empty variable).
Fix
Dockerfile (correct):
ARG APP_VERSION=1.0.0
FROM alpine:3.21
ARG APP_VERSION
RUN echo "Version: $APP_VERSION" > /versionExplanation: ARG values declared before FROM are available in FROM expressions but MUST be re-declared (without default value) inside each stage that needs them. The re-declared ARG inherits the value from the outer scope.
---
9. Platform Mismatch -- Building on Apple Silicon for Linux/amd64
Reproducing the Error
Build on M1/M2 Mac (arm64):
docker build -t myapp .Running on amd64 server:
standard_init_linux.go:228: exec user process caused: exec format errorFix
Option 1: Specify platform at build time:
docker build --platform linux/amd64 -t myapp .Option 2: Multi-platform build:
docker buildx create --use
docker buildx build --platform linux/amd64,linux/arm64 -t myapp --push .Option 3: Specify in Dockerfile for cross-compilation (Go example):
# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM golang:1.22-alpine AS build
ARG TARGETOS TARGETARCH
WORKDIR /src
COPY . .
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH go build -o /app
FROM alpine:3.21
COPY --from=build /app /usr/bin/app
CMD ["/usr/bin/app"]This builds the Go binary using the host's native architecture (fast, no emulation) but cross-compiles for the target platform.
---
10. Permission Error -- USER Before Package Install
Reproducing the Error
Dockerfile (broken):
FROM node:20-alpine
RUN addgroup -S app && adduser -S app -G app
USER app
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
CMD ["node", "server.js"]Error:
npm ERR! Error: EACCES: permission denied, mkdir '/app/node_modules'Fix
Dockerfile (correct):
FROM node:20-alpine
RUN addgroup -S app && adduser -S app -G app
WORKDIR /app
COPY --chown=app:app package*.json ./
RUN npm ci --production
COPY --chown=app:app . .
USER app
CMD ["node", "server.js"]Key principle: Install packages and set up the application BEFORE switching to the non-root USER. Use COPY --chown to ensure files are owned by the correct user.
---
11. Exec Format Error -- CRLF Line Endings in Scripts
Reproducing the Error
entrypoint.sh (created on Windows with CRLF endings):
#!/bin/bash
echo "Starting app"
exec "$@"Dockerfile:
FROM alpine:3.21
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["echo", "hello"]Error:
standard_init_linux.go:228: exec user process caused: no such file or directoryCause: The \r\n (CRLF) line endings make the kernel unable to find the interpreter (/bin/bash\r does not exist).
Fix
Option 1: Convert in Dockerfile:
FROM alpine:3.21
RUN apk add --no-cache dos2unix
COPY entrypoint.sh /entrypoint.sh
RUN dos2unix /entrypoint.sh && chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["echo", "hello"]Option 2: Fix at source (preferred):
# Convert before building
dos2unix entrypoint.sh
# Or configure Git to auto-convert
echo "*.sh text eol=lf" >> .gitattributesOption 3: Use heredoc to create the script inline (avoids line ending issues entirely):
# syntax=docker/dockerfile:1
FROM alpine:3.21
COPY <<'EOF' /entrypoint.sh
#!/bin/sh
set -e
echo "Starting app"
exec "$@"
EOF
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["echo", "hello"]---
12. Build Context Too Large -- Missing .dockerignore
Reproducing the Error
Project structure:
myapp/
node_modules/ (500 MB)
.git/ (200 MB)
src/ (2 MB)
DockerfileBuild output:
Sending build context to Docker daemon 702.3MBBuild takes several minutes just to transfer context.
Fix
Create `.dockerignore`:
node_modules
.git
dist
build
*.log
.env
.env.*
.vscode
.ideaResult:
Sending build context to Docker daemon 2.1MBBuild context transfer drops from minutes to under a second.
---
13. ENV Persistence Leak
Reproducing the Error
Dockerfile (broken):
FROM alpine:3.21
ENV SECRET_TOKEN=abc123
RUN some-build-command --token=$SECRET_TOKEN
RUN unset SECRET_TOKENProblem: SECRET_TOKEN is STILL in the final image:
docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' myimage
# Output includes: SECRET_TOKEN=abc123Fix
Option 1: Use ARG instead of ENV (if only needed at build time):
FROM alpine:3.21
ARG SECRET_TOKEN
RUN some-build-command --token=$SECRET_TOKENOption 2: Use secret mount (preferred for actual secrets):
# syntax=docker/dockerfile:1
FROM alpine:3.21
RUN --mount=type=secret,id=token,env=SECRET_TOKEN \
some-build-command --token=$SECRET_TOKENOption 3: Use inline export (if ENV is needed temporarily):
FROM alpine:3.21
RUN export SECRET_TOKEN=abc123 \
&& some-build-command --token=$SECRET_TOKEN \
&& unset SECRET_TOKENNEVER use ENV for secrets. ENV values persist in the final image and are visible via docker inspect and docker history.