How to Make Docker Build Run Faster
A simple tip to optimize build time in Docker.
Join the DZone community and get the full member experience.Join For Free
In this article, let's discuss how to run a Docker build faster with a simple tip.
Let’s assume we are containerizing an Angular application. We created a Dockerfile in the project’s root directory:
Let's build our Angular project first.
After the build, the project directory looks like:
Let's build the Docker image now.
docker build command took approximately 53 seconds to run.
On a side note, you can calculate the time taken to run any command in Linux/Mac by appending the word time before your command
> time docker build -t my-img .
The Nginx image we used to build our Docker image is just 20.6MB in size. Why is it taking 53 seconds to build such a small Docker image?
The culprit here is the build context.
Understanding the Build Context
docker build -t my-img . command, you might have noticed the . (dot) at the end, which implies:
- The Dockerfile resides in the current directory
- The build context is set in the current directory
The Docker build command will first compress and create a TAR file of everything inside Build Context’s directory. Then that file will be sent to the Docker daemon to build the image.
Since we kept the Dockerfile in the project root directory, the build command is creating a TAR file of the entire root directory of the project (including the node_modules folder).
That's why we are seeing "Sending build context to Docker daemon 378.9MB" in the output, meaning 378.9MB are transferred to the Docker daemon to build the Docker image.
Note: The Docker daemon could be running either in our local system or on a remote server. If it's remote, we will be sending 378 MB data to the Docker daemon on a remote server for every single build command.
How to Avoid This
Don’t create the Dockerfile in the project root directory! Always create the Dockerfile or docker-compose file inside the Docker folder.
What's the Catch With This Solution?
Dockerfile can only refer to files/folders available in its current directory or its subdirectories.
In our Angular Application, we need content from the dist folder to build our Docker image. The dist folder usually gets generated in the root directory by the ng build command.
If we moved the Dockerfile to the Docker folder, we can’t refer to the dist folder from Dockerfile.
How to Fix This
In the angular.json file, change "outputPath": "dist/my-app" to "outputPath": "Docker/dist/my-app"
This will ensure the dist folder gets generated inside the Docker folder all the time.
After, let's run
docker build from inside the Docker folder:
- Only 273.4KB are sent to the Docker daemon from the build context
- Build completed in just 1.079 seconds
This same technique can be applied for Spring boot applications as well.
Spring Boot Application
In a Spring Boot application, let's start by creating a Dockerfile in the root directory.
mvn clean package, let's try building our docker image:
As you can see, the docker build command sent 81 MB from the build context to the Docker daemon, and the build took nearly 12 seconds to complete.
Now let's move the Dockerfile to a separate folder, say Docker. Instead of manually copy-pasting the JAR/WAR file from the target folder to the Docker folder, we tweaked the spring-boot-maven-plugin a little.
After the mvn clean package command, our folder structure will look something like:
Now run the Docker build command from inside the Docker folder:
Now the Docker build only sends 40 MB (size of EmpApp.jar) to the Docker daemon and the entire build took only 4.49 seconds.
That's all folks!
Published at DZone with permission of Vicky AV. See the original article here.
Opinions expressed by DZone contributors are their own.