Optimizing Docker Images Using Multistage Builds
In this post I will mention some of the rules and tricks to generate optimized Docker images.
Multistage builds
Multi-stage builds are useful to optimize Dockerfiles while keeping them easy to read and maintain.
By using multistage build technique we can reduce the size of our docker image. The key point to is that we do not need to worry much about bringing in extra resources to build our application, and we can still run a lean production container. Multistage containers also encourage doing builds inside Docker, which is a great pattern for repeatability in your build system.
In the past, it was common practice to have one Dockerfile for development, and another, slimmed-down one to use for production. The development version contained everything needed to build your application. The production version only contained your application and the dependencies needed to run it.
To write a truly efficient Dockerfile, you had to come up with shell tricks and arcane solutions to keep the layers as small as possible. All to ensure that each layer contained only the artifacts it needed, and nothing else.
You can read about the multistage here.
- With multi-stage builds, we can use multiple
FROM
statements in the Dockerfile. - Each
FROM
instruction can use a different base, and each of them begins a new stage of the build. You
can selectively copy artifacts from one stage to another, leaving behind everything you don’t want in the final image.
# syntax=docker/dockerfile:1
FROM ubuntu:22.04 as system_builder
USER root
RUN apt-get update && \
apt-get install -y --no-install-recommends gfortran gcc libomp-dev curl git \
python3 python3-pip cmake ninja-build \
liblapack-dev libopenblas-dev libhdf5-dev \
libplplot-dev plplot-driver-cairo libboost-all-dev \
gnuplot doxygen libgtk-4-dev && apt-get clean
FROM system_builder
ENV EASIFEM_BUILD_DIR /easifem/build
ENV EASIFEM_SOURCE_DIR /easifem/src
ENV EASIFEM_INSTALL_DIR /easifem/install
ENV EASIFEM_TEST_DIR /easifem/tests
COPY ./tests/* $EASIFEM_TEST_DIR/
WORKDIR $EASIFEM_TEST_DIR
RUN gfortran -o main.out main.F90 && ./main.out
The first line
# syntax=docker/dockerfile:1
tells Docker that we are going to use a newer version of the Dockerfile frontend which will require BuildKit’s new features.
We can stop the build at particular stage. For example, in the following example, we stop only build the system_builder
image.
DOCKER_BUILDKIT=1 docker image build --target system_builder -t vickysharma0812/easifem-system:latest .
Note that we have enable
BuiltKit
by specifyingDOCKER_BUILDKIT=1
.
In the line
FROM system_builder
we are using previous stage as new stage.
You can read more about multistage build at official website of docker.