Pages

Saturday, March 16, 2019

Docker - Multi Stage Build

Containers are the running instance of an Image. While working with Docker and other container technologies, though the size of the image does not matter but having larger images will sure consume lot of disk space. If we save the images in the local registry or having them in /var/lib/docker, the disk space needs to be cleared very often.

Having larger images requires cleaning them very often. Docker from version 17 has introduced a feature that helps in creating thin docker images, in other words small, short docker images. The feature is called multi-stage-build. This feature allows the reuse of artifacts produced by one stage from another stage. This helps in creating smaller images.

The old way - Lets say i want to create a Docker images for one of my java application. The current Dockerfile looks something like this,
jagadishsampleUtils$Fri Mar 15@ cat old-Dockerfile
FROM maven:3.5.2
COPY src /usr/src/app/src
COPY pom.xml /usr/src/app
VOLUME /Users/jagadish/.m2
RUN mvn -f /usr/src/app/pom.xml package
EXPOSE 8080
ENTRYPOINT [“java”, “-classpath”, “/usr/src/app/target/sampleUtils-1.0-SNAPSHOT.jar com.sample.core.bank.App”]
The Dockerfile looks simple. All i want to run is the application using “java -classpath /usr/src/app/target/sampleUtils-1.0-SNAPSHOT.jar com.sample.core.bank.App”

Now from the Dockerfile, i am using a maven:3.5.2 base image, uploading the source code and then running the “mvn install package command”. This will inturn install many dependency libraries. Once the command is successfully, it generates the jar file where i used to run my application. But if you observe for running our application all we need to is the jar file but our image file is going to have our source code, downloaded dependency jar file etc. This could take up the image size to 748 mb.

What if we have a way where we build the image such only jar file is left in the image rather than all other things. Multi-stage build helps in this case.

The new Way - The multistage build will have the generated jar file from the first image file. Here is how the Dockerfile looks,
jagadishsampleUtils$Fri Mar 15@ cat Dockerfile
FROM maven:3.5.2 AS build
COPY src /usr/src/app/src
COPY pom.xml /usr/src/app
VOLUME /Users/jagadish/.m2
RUN mvn -f /usr/src/app/pom.xml package
 
FROM openjdk:8
COPY --from=build usr/src/app/target/sampleUtils-1.0-SNAPSHOT.jar /usr/app/sampleUtils-1.0-SNAPSHOT.jar

In the above image file, we are creating a image file with copying the source code, running maven command and naming the image file as build. The FROM element talks about this, FROM maven:3.5.2 AS build

Once the build image is created, i am using the build as reference and copying the generated jar file from this image to second created image using the,

FROM openjdk:8
COPY --from=build usr/src/app/target/sampleUtils-1.0-SNAPSHOT.jar /usr/app/sampleUtils-1.0-SNAPSHOT.jar

Once the image is generated, we will be having only the jar file and java. This will reduce the image size. Once the iamge is created, the size of the image will be around 624 mb which got reduced by 120mb from the old way.

More to Come. Happy Learning :-)

No comments :

Post a Comment