Docker Build Context Reference
Understand and optimize the Docker build context for faster, more efficient builds
Syntax
The build context is the set of files located at the specified PATH or URL that Docker sends to the Docker daemon during the build process. It provides the files that can be referenced by ADD or COPY instructions in the Dockerfile.
The Docker build context is a fundamental concept in Docker that defines the set of files available to the Docker daemon during a build process. When you run a docker build
command, the CLI sends the entire build context to the daemon as part of the build process. This context includes the Dockerfile and any files referenced by instructions like ADD and COPY.
Understanding and optimizing the build context is essential for efficient Docker builds, especially in large projects where the context size can significantly impact build performance.
How the Build Context Works
When you run a docker build
command, the following steps occur:
- The entire directory specified by PATH is sent to the Docker daemon as the build context.
- The Docker daemon processes the Dockerfile, executing each instruction in order.
- When the Dockerfile contains ADD or COPY instructions, files are copied from the build context into the image.
The build context is sent to the Docker daemon regardless of whether you're building locally or using a remote Docker daemon. This is important to understand, as sending a large build context over the network can significantly slow down the build process.
By default, Docker looks for a Dockerfile at the root of the build context. You can specify an alternative Dockerfile location using the -f
or --file
flag:
docker build -f path/to/Dockerfile .
In this command, .
represents the build context (the current directory), while -f path/to/Dockerfile
specifies the Dockerfile location.
Build Context Sources
The most common build context source is a local directory. Docker will use all files in the specified directory as the build context:
docker build .
In this example, .
refers to the current directory.
You can specify a Git repository URL as the build context. Docker will clone the repository and use it as the build context:
docker build https://github.com/user/repo.git#branch:subdirectory
This command clones the specified Git repository, checks out the specified branch, and uses the subdirectory as the build context.
Docker can use a tar archive as the build context. This can be provided either remotely via HTTP or as a local file:
docker build http://server/context.tar.gz
docker build - < context.tar.gz
You can pass a Dockerfile directly via STDIN by using the -
(hyphen) character as the build context:
docker build - < Dockerfile
echo -e 'FROM alpine\nRUN echo "Hello, World!"' | docker build -
When using STDIN as the build context, you can't use ADD or COPY commands in your Dockerfile, as there are no files available in the context.
Controlling the Build Context
The most important tool for controlling the build context is the .dockerignore
file. This file uses patterns similar to .gitignore
to specify which files and directories should be excluded from the build context:
# Example .dockerignore file
node_modules
npm-debug.log
.git
.gitignore
*.md
*.log
dist
coverage
.env
.DS_Store
Using .dockerignore
effectively can significantly reduce the size of the build context, leading to faster builds and better layer caching.
You can specify a subdirectory of your project as the build context to limit what files are included:
docker build ./app
This command uses only the ./app
directory as the build context, excluding other directories in your project.
You can place your Dockerfile outside the build context and reference it with the -f
flag:
docker build -f ../Dockerfiles/Dockerfile.prod ./app
This command uses ./app
as the build context but uses a Dockerfile located at ../Dockerfiles/Dockerfile.prod
.
Examples of Build Context Usage
Basic Build Context
Using the current directory as the build context:
docker build -t myapp:1.0 .
This command sends the entire current directory to the Docker daemon as the build context. The Dockerfile is assumed to be at the root of this directory.
Custom Dockerfile Location
Specifying a different Dockerfile location while using the current directory as the context:
docker build -f docker/Dockerfile.prod -t myapp:prod .
This command uses a Dockerfile at docker/Dockerfile.prod but still includes the entire current directory in the build context.
Limited Build Context
Using a specific subdirectory as the build context to reduce context size:
docker build -t myapp:1.0 ./src
This command only sends the ./src directory to the Docker daemon as the build context, excluding other directories in the project.
Git Repository as Context
Building directly from a Git repository:
docker build -t myapp:latest https://github.com/user/repo.git
Docker will clone the repository and use it as the build context. This is useful for CI/CD pipelines or building from a specific repository version.
Using .dockerignore
Creating a comprehensive .dockerignore file for a Node.js project:
# .dockerignore
node_modules
npm-debug.log
yarn-error.log
.git
.gitignore
.github
.vscode
*.md
*.log
coverage
.env
.env.*
dist
build
.DS_Store
**/.DS_Store
.npm
.eslintcache
This .dockerignore file excludes common directories and files that aren't needed in the build context for a Node.js application.
BuildKit Inline Cache
Using BuildKit's inline cache with the build context:
DOCKER_BUILDKIT=1 docker build --build-arg BUILDKIT_INLINE_CACHE=1 -t myapp:latest .
This command enables BuildKit and its inline cache feature, which can improve build performance by caching layer metadata in the image itself.
Best Practices for Build Context
- Keep the build context small: Include only the files necessary for building your image to improve build performance.
- Use .dockerignore effectively: Create a comprehensive .dockerignore file to exclude unnecessary files and directories.
- Structure your project thoughtfully: Organize your project so that you can use smaller, more focused build contexts when possible.
- Use subdirectories as contexts: When building multiple Docker images from a single repository, consider using subdirectories as separate build contexts.
- Be careful with COPY/ADD commands: Only copy what you need into the image, and be specific about what you copy rather than using wildcard patterns like
COPY . .
. - Monitor build context size: Pay attention to the "Sending build context to Docker daemon" message to track how large your context is.
- Consider multi-stage builds: Use multi-stage builds to keep the final image small, even if the build context includes many files.
- Leverage BuildKit: Enable BuildKit (
DOCKER_BUILDKIT=1
) for improved build performance and additional features. - Use external Dockerfiles when appropriate: If your Dockerfile is not in the build context, use the -f flag to specify its location.
- Be aware of symlinks: Docker follows symlinks in the build context, which can sometimes include unintended files.
Advanced Build Context Techniques
Docker BuildKit supports external resources in Dockerfiles, allowing you to reference resources outside the build context:
# Syntax must be set for BuildKit features
# syntax=docker/dockerfile:1.4
FROM alpine
# Copy from HTTP source directly, no need to include in build context
ADD --checksum=sha256:36b2b2a4802d52d3f527471e8a66d73daed88962b1e0f937ec48a2b567bcc9c0 \
https://example.com/files/myfile.tar.gz /usr/local/
RUN tar -xzf /usr/local/myfile.tar.gz -C /usr/local/
This feature requires BuildKit to be enabled and allows you to reference resources that don't need to be included in the build context.
In multi-stage builds, the build context is the same for all stages, but you can selectively copy files between stages:
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
# Only copy what's needed from the builder stage
COPY --from=builder /app/dist /usr/share/nginx/html
This approach allows you to have a large build context for the build stage but keep the final image small by copying only the necessary files.
BuildKit allows you to mount SSH agents and secrets during the build, which can be useful for accessing private repositories or credentials without including them in the build context:
# Build with SSH agent forwarding
DOCKER_BUILDKIT=1 docker build --ssh default=$SSH_AUTH_SOCK .
# In Dockerfile
# syntax=docker/dockerfile:1.4
FROM alpine
RUN --mount=type=ssh git clone [email protected]:private/repo.git
This feature allows you to access protected resources during the build without adding sensitive information to the build context or the final image.
You can combine different sources for the Dockerfile and build context:
# Use a Dockerfile from Git but provide context via STDIN
docker build -f https://github.com/user/repo/raw/branch/Dockerfile - < context.tar.gz
This approach allows for flexible build configurations, especially in CI/CD environments.
Troubleshooting Build Context Issues
If your build is slow because of a large build context, you can investigate which files are being included:
# Check the size of your potential build context
du -sh .
# Find large files in your directory
find . -type f -size +10M | sort -rh
# Test what .dockerignore would exclude
find . -type f -not -path "*/\.*" | grep -v -f .dockerignore
Use this information to refine your .dockerignore file or restructure your project.
If files referenced in your Dockerfile can't be found during the build:
- Check that the files exist in the build context, not just on your local filesystem.
- Ensure the files aren't being excluded by .dockerignore.
- Verify that the paths in COPY or ADD instructions are correct relative to the build context, not the Dockerfile location.
Path resolution in Dockerfiles can be confusing, especially when using external Dockerfiles:
# The context is ./app, but the Dockerfile is in ../Dockerfiles
docker build -f ../Dockerfiles/Dockerfile.prod ./app
In this example, paths in COPY/ADD instructions must be relative to ./app (the context), not to ../Dockerfiles (where the Dockerfile is located).
Notes and Limitations
- The build context is limited to the files in the specified directory or URL. You can't use COPY or ADD to access files outside this context.
- The maximum size of the build context depends on available resources. Very large contexts can cause out-of-memory errors or extremely slow builds.
- When using a remote Docker daemon, the entire build context must be transferred over the network, which can be slow for large contexts.
- BuildKit features like external resources, SSH mounting, and secret mounting require BuildKit to be enabled (
DOCKER_BUILDKIT=1
or Docker version 23.0 or later). - The .dockerignore file must be at the root of the build context to be effective. If you specify a subdirectory as the context, the .dockerignore file must be in that subdirectory.
- Docker follows symlinks within the build context, which can sometimes include more files than expected.
- The build context is processed before the Dockerfile is parsed, so changes made by RUN instructions can't affect what files are available in the context.
- When using STDIN for the Dockerfile (-), the build context is empty, so you can't use COPY or ADD instructions.