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.
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 https://github.com/pwaller/docker-show-context.git
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)
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.
Thank you very much!