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: Docker container health status unhealthy
How to fix Docker container health check failing with unhealthy status, including HEALTHCHECK syntax, timing issues, missing curl/wget, endpoint problems, and Compose healthcheck configuration.
Fix: Docker Compose Service failed to build / ERROR building
How to fix Docker Compose Service failed to build errors caused by wrong Dockerfile paths, YAML syntax issues, build args, platform mismatches, and network failures.
Fix: Docker exec /entrypoint.sh: no such file or directory
How to fix Docker entrypoint not found error caused by wrong file path, Windows line endings, missing shebang, wrong base image, and multi-stage build issues.
Fix: AWS CloudFormation stack in ROLLBACK_COMPLETE or CREATE_FAILED state
How to fix AWS CloudFormation ROLLBACK_COMPLETE and CREATE_FAILED errors caused by IAM permissions, resource limits, invalid parameters, and dependency failures.