Fix: Docker build sending large build context / slow Docker build
Quick Answer
How to fix Docker build sending large build context caused by missing .dockerignore, node_modules in context, large files, and inefficient Dockerfile layers.
The Error
You run docker build and see:
Sending build context to Docker daemon 2.5GBThe build takes forever, uses excessive disk space, or fails with:
Error response from daemon: Error processing tar file: exit status 1COPY failed: file not found in build context or excluded by .dockerignoreno space left on deviceDocker sends the entire build context (the directory you specify) to the Docker daemon before starting the build. If that directory contains large files, node_modules, .git, or data files, the build context is unnecessarily huge.
Why This Happens
When you run docker build ., Docker tars up the entire current directory and sends it to the daemon. This is the “build context.” Every file in that directory is included unless excluded by .dockerignore.
Common causes:
- Missing
.dockerignorefile. Everything is included by default. node_modules/in the context. Can be hundreds of megabytes..git/directory. Repository history can be very large.- Data files, logs, or databases. SQLite databases, CSV files, logs.
- Build artifacts.
dist/,build/,target/,__pycache__/. - Large binary files. Videos, images, trained ML models.
- Wrong build context path. Running
docker build /instead ofdocker build ..
Fix 1: Create a .dockerignore File
The most important fix. Create .dockerignore in your project root:
# Dependencies
node_modules
.npm
bower_components
vendor
# Version control
.git
.gitignore
.svn
# Build artifacts
dist
build
target
__pycache__
*.pyc
*.pyo
# IDE and editor files
.idea
.vscode
*.swp
*.swo
*~
# OS files
.DS_Store
Thumbs.db
# Docker files (not needed in the image)
Dockerfile
docker-compose.yml
docker-compose*.yml
.dockerignore
# Documentation
README.md
CHANGELOG.md
LICENSE
docs
# Test files
coverage
.nyc_output
*.test.js
*.spec.js
__tests__
# Environment and secrets
.env
.env.*
*.pem
*.key
# Logs
*.log
logs
# Data files
*.sql
*.sqlite
*.csv
dataVerify what is included in the context:
# See what Docker would include (without actually building)
# Create a tar and check its size
tar -cf - --exclude='.git' . | wc -c
# Or use docker build with progress
docker build --progress=plain .Pro Tip: A good
.dockerignoreis as important as a good.gitignore. Start with everything excluded and only include what the build actually needs. This can reduce build context from gigabytes to megabytes and speed up builds dramatically.
Fix 2: Use Multi-Stage Builds
Multi-stage builds keep the final image small:
Before — everything in one stage:
FROM node:22
WORKDIR /app
COPY . .
RUN npm ci
RUN npm run build
# Final image includes source code, node_modules, AND build outputAfter — multi-stage:
# Build stage
FROM node:22 AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Production stage
FROM node:22-alpine
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY --from=build /app/node_modules ./node_modules
COPY package*.json ./
EXPOSE 3000
CMD ["node", "dist/index.js"]For Go applications:
FROM golang:1.23 AS build
WORKDIR /app
COPY go.* ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /server
FROM scratch
COPY --from=build /server /server
ENTRYPOINT ["/server"]The final image only contains the compiled binary — no source code, no build tools.
Fix 3: Optimize COPY Order for Layer Caching
Docker caches layers. If a layer has not changed, Docker reuses the cache. Order your COPY instructions to maximize cache hits:
Bad — COPY everything first (cache invalidated on any file change):
COPY . .
RUN npm ci
RUN npm run buildGood — copy dependency files first, then source:
# Layer 1: Copy only dependency files (rarely change)
COPY package.json package-lock.json ./
RUN npm ci
# Layer 2: Copy source (changes frequently)
COPY . .
RUN npm run buildNow npm ci is cached unless package.json or package-lock.json changes. Source code changes only invalidate the last two layers.
For Python:
COPY requirements.txt ./
RUN pip install -r requirements.txt
COPY . .For Go:
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o /appCommon Mistake: Putting
COPY . .beforeRUN npm ci. This means any source code change invalidates the npm install cache, forcing a full reinstall every build. Always copy dependency manifests separately.
Fix 4: Use Specific COPY Paths
Instead of COPY . ., copy only what you need:
# Instead of COPY . .
COPY src/ ./src/
COPY public/ ./public/
COPY package.json package-lock.json tsconfig.json ./This reduces the context that matters and makes the build more predictable.
For large monorepos:
# Only copy the relevant workspace
COPY packages/my-service/package.json ./
COPY packages/my-service/src/ ./src/
COPY packages/shared/src/ ./shared/src/Fix 5: Use BuildKit for Faster Builds
Docker BuildKit is faster and more efficient:
# Enable BuildKit
DOCKER_BUILDKIT=1 docker build .
# Or set it permanently
export DOCKER_BUILDKIT=1
# In Docker Desktop, BuildKit is enabled by defaultBuildKit advantages:
- Parallel layer building
- Better caching
- Secret mounts (no secrets in layers)
- SSH forwarding
Mount secrets without storing in the image:
# syntax=docker/dockerfile:1
RUN --mount=type=secret,id=npm_token \
NPM_TOKEN=$(cat /run/secrets/npm_token) npm cidocker build --secret id=npm_token,src=.npmrc .Fix 6: Check Build Context Size
Measure your build context:
# Quick check — how big is the directory?
du -sh --exclude=.git .
# What's taking the most space?
du -h --max-depth=1 . | sort -rh | head -20
# Build with verbose output to see context size
docker build --progress=plain . 2>&1 | head -5
# Sending build context to Docker daemon 15.2MBTarget: Under 50MB. If your context is over 100MB, you almost certainly need a better .dockerignore.
Fix 7: Use Remote Build Context
Build from a Git URL instead of a local directory:
# Build from a Git repository
docker build https://github.com/user/repo.git#main
# Build from a specific directory in the repo
docker build https://github.com/user/repo.git#main:docker/
# Build from a tarball URL
docker build https://example.com/context.tar.gzUse stdin for the Dockerfile:
docker build -f - . << 'EOF'
FROM alpine
RUN echo "hello"
EOFFix 8: Use .dockerignore Patterns Effectively
.dockerignore supports the same pattern syntax as .gitignore:
# Exclude everything
*
# Include only what's needed
!src/
!package.json
!package-lock.json
!tsconfig.json
!.env.example
# Exclude within included directories
src/**/*.test.ts
src/**/*.spec.tsThe “exclude everything, include selectively” pattern is the most effective approach for large projects. It guarantees only the minimum files are in the context.
Test your .dockerignore:
# List files that would be included in the build context
# (No built-in Docker command, but you can simulate it)
rsync -avn --exclude-from=.dockerignore . /dev/nullStill Not Working?
Check for symlinks. Symlinked directories can include unexpected large directories in the context.
Check for Docker disk space:
docker system df
# Shows space used by images, containers, volumes, and cache
docker system prune
# Removes unused dataUse --no-cache for debugging:
docker build --no-cache .Consider using Kaniko, Buildpacks, or Nix for alternative build strategies that do not require a build context.
For Docker permission issues, see Fix: Docker permission denied socket. For Docker entrypoint errors, see Fix: Docker exec /entrypoint.sh: no such file or directory. For Docker container name conflicts, see Fix: Docker container name already in use.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: Coolify Not Working — Deployment Failing, SSL Not Working, or Containers Not Starting
How to fix Coolify self-hosted PaaS issues — server setup, application deployment, Docker and Nixpacks builds, environment variables, SSL certificates, database provisioning, and GitHub integration.
Fix: Docker Secrets Not Working — BuildKit --secret Not Mounting, Compose Secrets Undefined, or Secret Leaking into Image
How to fix Docker secrets — BuildKit secret mounts in Dockerfile, docker-compose secrets config, runtime vs build-time secrets, environment variable alternatives, and verifying secrets don't leak into image layers.
Fix: Docker Compose Healthcheck Not Working — depends_on Not Waiting or Always Unhealthy
How to fix Docker Compose healthcheck issues — depends_on condition service_healthy, healthcheck command syntax, start_period, custom health scripts, and debugging unhealthy containers.
Fix: Docker Multi-Platform Build Not Working — buildx Fails, Wrong Architecture, or QEMU Error
How to fix Docker multi-platform build issues — buildx setup, QEMU registration, --platform flag usage, architecture-specific dependencies, and pushing multi-arch manifests to a registry.