Skip to main content

Docker Context

The set of files and directories sent to the Docker daemon when building an image. Docker reads everything in the build context directory and sends it to the daemon — making a small, well-scoped context essential for fast builds.

Docker Context — What Gets Sent to the Daemon During Build

What Is the Docker Build Context in Simple Terms?

When you run docker build ., the . is the build context — it tells Docker which directory to use as the source of files for the build. Docker reads everything in that directory (except what is in .dockerignore) and sends the entire content to the Docker daemon before a single Dockerfile instruction is executed.

This means if your project directory contains a node_modules folder with 500MB of packages, Docker sends 500MB to the daemon even if you never use those files in the Dockerfile. A large build context is one of the most common causes of slow Docker builds.

Bash
+------------------------------------------+
| Your project directory (build context) |
| |
| /src/ <- your source code |
| /node_modules/<- 500MB of packages |
| /.git/ <- git history |
| /tests/ <- test files |
| /.env <- secrets! |
+------------------------------------------+
|
| docker build .
| Sends EVERYTHING to daemon
v
+------------------------------------------+
| Docker Daemon |
| Receives entire context (1.2GB) |
| Then starts executing Dockerfile |
+------------------------------------------+
With .dockerignore:
+------------------------------------------+
| /src/ <- your source code |
+------------------------------------------+
|
| docker build .
| Sends only what is not ignored (2MB)
v
+------------------------------------------+
| Docker Daemon receives 2MB not 1.2GB |
| Build starts in seconds not minutes |
+------------------------------------------+

Measuring Build Context Size

Bash
# The first line of docker build output shows context size
docker build .
# Sending build context to Docker daemon 1.2GB
# <- 1.2GB sent before a single instruction runs
# With .dockerignore:
docker build .
# Sending build context to Docker daemon 2.3MB
# <- 2.3MB — 520x reduction
# Why context size matters:
# 1.2GB context on a local network: ~5-10 seconds
# 1.2GB context on remote build server: 30-60 seconds
# 2.3MB context: < 1 second in either case

The .dockerignore File

Bash
# .dockerignore — same syntax as .gitignore
# Node.js
node_modules/
npm-debug.log
.npm/
.yarn/
# Build output (built inside container, not copied from host)
dist/
build/
.next/
out/
# Version control
.git/
.gitignore
.gitattributes
# Environment files — NEVER copy secrets into images
.env
.env.*
!.env.example
# Development tools
.vscode/
.idea/
*.swp
*.swo
# Tests
coverage/
.nyc_output/
__tests__/
*.test.ts
*.spec.ts
*.test.js
*.spec.js
# Docker files
Dockerfile
Dockerfile.*
docker-compose.yml
docker-compose.*.yml
# Documentation
docs/
*.md
README.md
# macOS
.DS_Store
# Python
__pycache__/
*.pyc
*.pyo
.pytest_cache/
venv/
.venv/

Using a Different Build Context

Bash
# Use current directory as context (most common)
docker build .
# Use a specific directory as context
docker build /path/to/project
# Use a different Dockerfile with same context
docker build -f Dockerfile.prod .
# Use a different Dockerfile AND different context
docker build -f /path/to/Dockerfile /path/to/context
# Build from a Git URL (context is the repository)
docker build https://github.com/myorg/myrepo.git#main
# Docker clones the repo and uses it as the build context
# Useful for building without needing the code locally
# Build from stdin (no context — no COPY instructions possible)
docker build - < Dockerfile
# or
cat Dockerfile | docker build -

Context vs .dockerignore vs COPY

Bash
Three levels of file inclusion:
1. Build context — what directory docker build uses
(controlled by the path argument in docker build .)
2. .dockerignore — which files WITHIN context are excluded
(reduces what is sent to the daemon)
3. COPY instruction — which files from context go INTO the image
(controls which context files end up in a layer)
Example:
Project has: src/, tests/, node_modules/, .env
.dockerignore excludes: node_modules/, .env, tests/
Context sent to daemon: src/ only
Dockerfile:
COPY src/ /app/src/ <- copies src into image
COPY . . <- would copy only src/ (tests/ excluded by .dockerignore)

Troubleshooting Reference

Problem Cause Fix
Build very slow even with cached layers Large build context Add .dockerignore to exclude node_modules, .git, build artifacts
COPY . . copies unwanted files No .dockerignore Create .dockerignore with exclusions
Secrets accidentally in image .env not in .dockerignore Add .env* to .dockerignore and rebuild
COPY fails with not found File excluded by .dockerignore Remove exclusion or use specific COPY instead of COPY . .
Tip

Create a .dockerignore file as the very first thing in every new project — before you write a single Dockerfile instruction. It is much easier to add it at the start than to debug why your builds are slow or why secrets ended up in an image layer six months later.

Common Mistake

Thinking that .dockerignore controls what ends up in the image. It does not — it controls what is sent to the daemon. To control what ends up in an image layer, use specific COPY src/ /app/src/ instructions instead of COPY . .. Both are needed for a correct setup: .dockerignore for build speed, specific COPY for image content.

Frequently Asked Questions

Why does a huge build context slow down docker build even before any instruction runs?

Before Docker executes a single Dockerfile instruction, it tars up the entire build context directory and streams it to the daemon (or BuildKit builder), because the daemon might be running remotely and needs local access to any files a COPY or ADD might reference. If that directory contains `node_modules`, `.git`, or build artifacts, you're paying to transfer hundreds of megabytes on every single build regardless of whether the Dockerfile ever uses them.

What's the standard fix for a bloated build context?

A `.dockerignore` file, using the same pattern syntax as `.gitignore`, to exclude `node_modules`, `.git`, log files, and local env files from what gets sent to the daemon. A common mistake is adding `.dockerignore` only after noticing slow builds rather than from day one — and forgetting that `.dockerignore` only affects the build context, not what ends up inside layers already copied by an earlier `COPY .` instruction.