The Docker build context refers to the files and directories that will be available to the Docker engine when you run
docker build. Anything not included in the build context won’t be accessible to commands in your
You should audit your use of
docker build to keep your build contexts small. Accidentally including unnecessary files can result in an excessively large build context, which will lead to longer builds.
What Is the Build Context?
Here’s a simple
docker build command:
docker build . -t my-image:latest
This builds a Docker image using the
Dockerfile found in your working directory. The resulting image will be tagged as
my-image:latest, although this detail isn’t important to this tutorial.
Dockerfile, you’ll likely use
COPY to add files and folders into your image:
FROM httpd:latest COPY index.html /usr/local/apache2/htdocs/index.html COPY css/ /usr/local/apache2/htdocs/css/
This example copies the
index.html file and
css directory into your container. At first glance, it looks like the
COPY statement simply references a path that’s resolved relative to your working directory.
This isn’t quite the case.
COPY can only access resources available in the build context. In this example, the build context is the working directory, so the files and folders within it are available. By default, Docker uses the contents of the directory passed to
docker build as the build context.
Why Is the Build Context Used?
The build context is important because the Docker CLI and Docker Engine might not be running on the same machine. When you run
docker build, the CLI sends the files and folders to build to the Docker engine. This set of files and folders becomes the build context.
Furthermore, not every build context is as straightforward as reusing your working directory. Docker also supports Git repository URLs as the path given to
docker build. In this case, the build context becomes the content of the specified repository.
The build context’s default “include all” behavior is fine for many small repositories. Problems become apparent once you add files to your working directory that aren’t used by your
Dockerfile. Resources such as prebuilt binaries, documentation files, and dependency libraries will be included in the build context even though they’re redundant.
Including too many assets in the build context can become a performance drain. You’re needlessly copying files that will never be used. The slowdown will be particularly evident if you’re connected to a remote Docker daemon or if you’re using a slow mechanical hard drive. You’ll see “sending build context to Docker daemon” in your shell while the copy is completed.
Docker does try to minimize redundant copying on its own. The BuildKit build backend—used since Docker 18.09—added support for incremental transfers. This means that Docker will usually only need to copy files added or changed since your last build. It’ll still copy the whole lot on the first build.
Excluding Resources from the Build Context
To resolve wasteful copying for good, you must tell Docker what it can omit from the build context. Let’s start by creating a
FROM node:latest WORKDIR /my-app COPY package.json package.json COPY package-lock.json package-lock.json COPY src/ . RUN npm install
Dockerfile could be used by an application written in Node.js. Node.js programs use
npm as their package manager. Packages are installed to a
node_modules folder. When you run
npm install locally, during development, the packages will be downloaded to the
node_modules folder in your working directory.
npm install itself to acquire the dependencies. This ensures that the image is fully self-contained. There’s no need to copy in the local
node_modules folder, as it’s not used by the
Despite this, Docker will still include the
node_modules folder in the default build context. To exclude it, create a
.dockerignore file in your working directory. This file has a similar syntax to
Any paths listed in
.dockerignore will be excluded from the build context. You should make sure that
.dockerignore is kept updated with changes to your project’s filesystem structure. You can substantially reduce Docker build context copying time by checking that only relevant paths (those actually used by your
Dockerfile) are present in the build context.
In the case of our example, the
node_modules folder could include thousands of files if we have a lot of dependencies in our project. Copying them to the Docker daemon as part of the build context could take several seconds and would be a wasteful operation. The
Dockerfile completely ignores them, fetching its own dependencies via
npm install instead.
Other Build Context Issues
.dockerignore can introduce other issues, too. A Dockerfile with this line is particularly problematic:
COPY . /my-app
This will copy everything in your working directory. This might seem like a good idea until you realize that your
.git history and any secret files will also end up within your container.
Copying an unfiltered build context also prevents Docker layer caching from working effectively. As something in your working directory will probably change between builds, Docker would need to run the
COPY instruction every time. This would create a new layer—and new layers for any subsequent instructions—even if the assets you’re interested in haven’t changed.
Compressing the Build Context
You can compress the build context to further improve build performance. Pass the
--compress flag to
docker build to apply gzip compression. The compression occurs before the context is sent to the Docker daemon.
docker build . -t my-image:latest --compress
This can improve performance in some scenarios. The compression adds its own overheads, though—your system now needs to compress the context, and the receiving Docker daemon has to uncompress it. Using compression could actually be slower than copying the original files, in some circumstances. Experiment with each of your images to assess whether you see an improvement.
The Docker build context defines the files that will be available for copying in your
Dockerfile. The build context is copied over to the Docker daemon before the build begins.
Build contexts default to including the contents of the directory or Git repository you passed to
docker build. You can omit items from the build context by creating a
.dockerignore file. This increases efficiency by reducing the amount of redundant data passed to the Docker daemon.