How to make Docker build faster reducing build context size

When you build a Docker image you will notice a “transferring context” step in the output (“Sending build context to Docker daemon” in older Docker versions) that can take a lot of time. This step is just Docker copying local files so keeping those to the minimum will make this step faster.

Output of docker build command where there's a line saying that Docker transferred 118.72MB to the build context and it took 11.8 seconds
docker build output

The build context are the files and directories that are accessible to the Docker engine when you run docker build command. You Dockerfile commands will only have access to the files and folders included in the build context.

Docker shows the build context size and transfer time in the output (118MB and 12 seconds in the example above). However, it doesn’t show the actual contents transferred. Knowing exactly what’s inside the build context is tricker because you have to pay attention to the globs added to the .dockerignore file.

Fortunately there’s a tool just for that: you can use docker-show-context to get details about the contents of the build context, including the biggest or slowest paths.

Preparing docker-show-context

Before you can use docker-show-context you have to build it. It’s a Docker image so you can build it by running the following command:

docker build -t docker-show-context
Code language: Shell Session (shell)

Now you will have a local Docker image tagged docker-show-context. Use this image to start a container that will analyze the build context of a given path. To specify which path you want to analyze, you must mount it as /data. For example, the command below analyzes the build context for the current directory:

docker run --rm -v $PWD:/data docker-show-context
Code language: Shell Session (shell)

Reducing build context of the example project

For all the examples in this article I’m using a newly created Vue 3 project. I created the project using Vue CLI 4.5.13:

yarn global add @vue/cli vue create hello-world
Code language: Bash (bash)

I added the following Dockerfile to build the project:

FROM node:lts-alpine3.14 AS builder WORKDIR /app COPY . ./ RUN yarn install --frozen-lockfile RUN yarn build FROM nginx:1.21-alpine WORKDIR /usr/share/nginx/html RUN rm -rf /usr/share/nginx/html COPY --from=builder /app/dist ./
Code language: Dockerfile (dockerfile)
docker-show-context output where you can see that node_modules appears several times in the build context statistics
docker-show-context output

If you review the output you will notice that the build context includes the entire node_modules folder. There is a step in the Dockerfile that will recreate node_modules from scratch (yarn install --frozen-lockfile) so we don’t need to copy that folder to the build context.

I should add node_modules to the .dockerignore file but that’s not enough: if you run docker-show-context again you will realize Docker is adding the internal .git folder to the build context. Docker was adding already the .git folder before but we didn’t notice because it is much smaller than node_modules.

In big repositories the .git folder could have a noticeable impact in the docker build process. It’s also something that can be easily missed: it’s a hidden folder and not specific from any programming language, IDE or build tool.

After exluding .git and .gitignore files, the build context of this example is reduced to just 0.38MB. Now it’s time you play a bit with docker-show-context find out why your build context is so big.

Leave a Reply

Your email address will not be published.

Required fields are marked *

Your avatar