πŸ”§ Error Fixes
Β· 5 min read
Last updated on

Docker Build Failed β€” How to Fix Common Docker Build Errors


ERROR: failed to solve: failed to compute cache key: failed to calculate checksum
COPY failed: file not found in build context
RUN apt-get install: E: Unable to locate package

Docker builds fail for many reasons β€” missing files, network issues, permission problems, or Dockerfile logic errors. Here’s every common cause with the fix.

How Docker builds work

When you run docker build ., Docker:

  1. Sends the build context (current directory minus .dockerignore) to the daemon
  2. Executes each Dockerfile instruction as a layer
  3. Caches layers β€” unchanged layers are reused from cache

Builds fail when a layer can’t execute: a file doesn’t exist in the context, a command returns non-zero, or a network request times out.

Fix 1: COPY/ADD β€” file not found in build context

The most common error. Docker can only access files within the build context (the directory you pass to docker build).

# ❌ File doesn't exist or is excluded by .dockerignore
COPY config/production.json /app/config/
# ERROR: failed to compute cache key: "/config/production.json" not found

Checklist:

# 1. Does the file exist relative to the Dockerfile?
ls config/production.json

# 2. Is it excluded by .dockerignore?
cat .dockerignore | grep config

# 3. Are you building from the right directory?
docker build -f docker/Dockerfile .  # Context is ".", not "docker/"

# 4. Is it a symlink? Docker doesn't follow symlinks outside the context
ls -la config/production.json

Fix:

# βœ… Ensure the path is relative to the build context (not the Dockerfile)
COPY ./config/production.json /app/config/

# βœ… If using a subdirectory Dockerfile, set context correctly
# docker build -f services/api/Dockerfile .  ← context is project root

Fix 2: apt-get β€” unable to locate package

The package index inside the base image is outdated or missing.

# ❌ No package index available
RUN apt-get install -y curl git
# E: Unable to locate package curl

# βœ… Always update before installing
RUN apt-get update && apt-get install -y \
    curl \
    git \
    && rm -rf /var/lib/apt/lists/*

Why rm -rf /var/lib/apt/lists/*? It removes the package index after installation, reducing the image size by 20-50MB.

For Alpine-based images:

# Alpine uses apk, not apt-get
RUN apk add --no-cache curl git

Fix 3: npm/yarn install fails

# ❌ package.json not copied before npm install
COPY . .
RUN npm install  # Fails if node_modules from host conflicts

# βœ… Copy package files first (also improves layer caching)
COPY package.json package-lock.json ./
RUN npm ci --production
COPY . .

Use npm ci instead of npm install in Docker β€” it’s faster, deterministic, and fails if package-lock.json is out of sync.

Common npm build failures:

# ❌ Native dependencies need build tools
RUN npm install  # node-gyp fails

# βœ… Install build dependencies first
RUN apt-get update && apt-get install -y python3 make g++ \
    && npm ci \
    && apt-get purge -y python3 make g++ \
    && rm -rf /var/lib/apt/lists/*

Fix 4: Build context too large (slow or OOM)

Sending build context to Docker daemon  2.5GB
# Build takes forever or runs out of memory

Fix: Create a .dockerignore file:

node_modules
.git
dist
build
*.log
.env
.venv
__pycache__
.next
coverage

Check context size:

# See what's being sent
du -sh $(docker build . 2>&1 | grep "Sending" | awk '{print $NF}') 2>/dev/null

# Or just check directory size minus .dockerignore
du -sh . --exclude=node_modules --exclude=.git

Fix 5: Permission denied during build

# ❌ Script not executable
COPY start.sh /app/
RUN /app/start.sh  # Permission denied

# βœ… Make it executable
COPY start.sh /app/
RUN chmod +x /app/start.sh

# βœ… Or set permissions in COPY (BuildKit)
COPY --chmod=755 start.sh /app/

For non-root users:

RUN adduser --disabled-password --gecos "" appuser
RUN chown -R appuser:appuser /app
USER appuser

Fix 6: Multi-stage build β€” file missing in final stage

Each FROM starts a fresh image. Files from previous stages don’t carry over automatically.

# Build stage
FROM node:20 AS builder
WORKDIR /app
COPY . .
RUN npm ci && npm run build

# Production stage
FROM node:20-slim
WORKDIR /app

# ❌ Forgot to copy build output β€” dist/ doesn't exist
CMD ["node", "dist/index.js"]

# βœ… Copy from builder stage
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
CMD ["node", "dist/index.js"]

Fix 7: Network errors during build

# ❌ Network timeout during package install
RUN pip install -r requirements.txt
# Could not fetch URL https://pypi.org/simple/...

# βœ… Add retry logic
RUN pip install --retries 3 --timeout 60 -r requirements.txt

# βœ… Or use a mirror
RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt

If behind a corporate proxy:

docker build --build-arg HTTP_PROXY=http://proxy:8080 --build-arg HTTPS_PROXY=http://proxy:8080 .

Fix 8: Cache invalidation causing unnecessary rebuilds

# ❌ Any change to source code invalidates npm install cache
COPY . .
RUN npm ci  # Re-runs every time ANY file changes

# βœ… Copy dependency files first β€” only re-runs when they change
COPY package.json package-lock.json ./
RUN npm ci
COPY . .  # Source changes don't invalidate npm cache

Order matters: Put instructions that change less frequently earlier in the Dockerfile.

Fix 9: Platform mismatch (ARM vs x86)

# ❌ Building on M1/M2 Mac, deploying to x86 Linux
# Image works locally but crashes in production

# βœ… Specify target platform
docker build --platform linux/amd64 .

# βœ… Or use multi-platform build
docker buildx build --platform linux/amd64,linux/arm64 .

Debugging Docker builds

# Verbose output (see every command's output)
docker build --progress=plain .

# Build without cache (start completely fresh)
docker build --no-cache .

# Build up to a specific stage
docker build --target builder .

# Inspect a failed layer β€” run a shell in the last successful layer
docker run -it <last-successful-image-id> /bin/sh

FAQ

Why does my build work locally but fail in CI?

Common causes: different Docker version, no cache in CI (use --cache-from), network restrictions in CI environment, or files that exist locally but aren’t committed to git.

How do I reduce my Docker image size?

Use multi-stage builds, Alpine-based images, .dockerignore, and combine RUN commands. A typical Node.js app can go from 1GB to 100MB with these techniques.

Should I use COPY or ADD?

Use COPY unless you specifically need ADD’s features (auto-extracting tar files, fetching URLs). COPY is more predictable and preferred in almost all cases.

How do I fix β€œno space left on device” during build?

docker system prune -a  # Remove all unused images, containers, volumes
docker builder prune     # Remove build cache
πŸ“˜