What is the build context, and what does .dockerignore do?

5 minintermediatebuild-contextdockerignore

Quick Answer

The build context is the set of files sent from your machine to the Docker daemon when you run docker build — by default, every file in the directory you specify (commonly .), which the daemon needs access to in order to satisfy any COPY/ADD instructions. .dockerignore excludes specified files/patterns from being sent as part of that context, which both speeds up the build (less data transferred and hashed) and prevents accidentally including sensitive or unnecessary files (like .git, node_modules, or .env files) in what's sent to the daemon or potentially copied into the image.

Detailed Answer

What the build context actually is

docker build -t myapp .

That trailing . isn't just "look at the Dockerfile here." It specifies the build context: the entire directory tree that Docker packages up and sends to the daemon before the build even starts. This allows any COPY/ADD instruction in the Dockerfile to reference files from it. This matters even for a remote daemon (see the CLI/daemon question). The whole context genuinely gets transferred over the network to wherever the daemon is running — it is not just referenced by path.

Sending build context to Docker daemon  245.7MB

This line is printed at the start of every docker build, and it deserves attention. A surprisingly large number here is a strong signal that unnecessary files are being included and transferred needlessly — for example, an entire node_modules directory, a .git history, or large data files unrelated to the application.

.dockerignore — excluding files from the context

# .dockerignore
.git
node_modules
npm-debug.log
.env
*.md
Dockerfile
.dockerignore

This functions similarly to .gitignore. Patterns listed here are excluded from what gets sent as the build context at all. This means they are not just "not copied into the image" — they are genuinely never transmitted to the daemon in the first place.

Why this matters for more than just speed

Performance: a smaller context transfers faster. This is especially relevant for a remote daemon or CI environment. It also reduces the daemon's own overhead from scanning and hashing the context for cache purposes.

Avoiding accidental inclusion of sensitive data: a broad COPY . . instruction copies everything in the build context that isn't excluded. Without a .dockerignore excluding .env, a local secrets file, or .git, a careless COPY . . can bake credentials directly into an image layer. This is especially risky for .git, since it can contain historical commits with sensitive data even if the current working tree doesn't. Image layers are effectively permanent once built and pushed. Removing a file in a later layer doesn't remove it from the earlier layer's stored data (recall the union filesystem question). Because of this, a leaked secret baked into an early layer is extremely difficult to fully scrub, even if a later commit or layer "deletes" it.

COPY . .    # without a .dockerignore, this could copy .env, .git, and other sensitive/unnecessary files

Avoiding cache invalidation from irrelevant files: recall that COPY's cache key depends on the actual content of copied files (see the layer caching question). If .git or build artifacts are part of the context and happen to change on every build, even without meaningful application changes, they can cause unnecessary cache invalidation for instructions that copy broad directories. An unexpectedly large "Sending build context" number should be treated as a signal to check the .dockerignore, not ignored.