Keeping Docker images small in a micro-services architecture is an important goal. Smaller images provide many key benefits:
It's tempting to start with a grand base image like centos or ubuntu so we don't miss any dependencies, but there are drastic differences in size. The centos 7 image is 193MB whereas Alpine weighs in at only an astonishing 5MB! Use only the minimum image necessary. Here are more comparisons. Beware though, that compact images like Alpine have a bit of a learning curve, it's missing the Bash shell for starters and uses ash instead.
During build time, read-only or intermediate layers are created for each instruction in the Dockerfile. These layers are like layers of a cake where subsequent layers are a delta of the prior one. Examples of commands that produce layers:
Docker will cache layers from earlier builds so you want the most stable layers first in the Dockerfile, order really matters.
Newer versions of the Docker engine support multi-stage builds, starting with Docker version 17.05. These let us skip the double ampersands and line continuations by creating stages of builds, all in a single Dockerfile. Just run docker build once.
- Pushes and pulls from image registries are quicker
- Builds are faster
- Dockerfiles are shorter
- Dependencies are reduced
- Services start and stop faster
- Enforces the notion of keeping services as ephemeral as possible, that is: stateless with minimal set up and configuration. See the Twelve-Factor App for details.
Please note: a newer version of this story is available on the Seasoned Developer Medium Site.
Use the smallest base image possible
It's tempting to start with a grand base image like centos or ubuntu so we don't miss any dependencies, but there are drastic differences in size. The centos 7 image is 193MB whereas Alpine weighs in at only an astonishing 5MB! Use only the minimum image necessary. Here are more comparisons. Beware though, that compact images like Alpine have a bit of a learning curve, it's missing the Bash shell for starters and uses ash instead.
Minimize layers and cleanup artifacts
During build time, read-only or intermediate layers are created for each instruction in the Dockerfile. These layers are like layers of a cake where subsequent layers are a delta of the prior one. Examples of commands that produce layers:
- FROM (specifies a base image)
- RUN (build time execution within the current build context)
- COPY (adds files from existing directory)
- CMD (specifies a container run time command)
One common approach to reduce layers is to combine multiple commands in a single statement, something like:
RUN apt-get install -y nginx \
&& rm -rf /var/lib/apt/lists/*
But using ampersands is considered error prone and difficult to read. In addition, the line continuation is easy to miss or accidentally remove. So this isn't ideal, but in this example at least we are cleaning up artifacts in the second line.
Speed up builds by keeping more frequently changing layers first in line
Docker will cache layers from earlier builds so you want the most stable layers first in the Dockerfile, order really matters.
Multi-stage builds
Newer versions of the Docker engine support multi-stage builds, starting with Docker version 17.05. These let us skip the double ampersands and line continuations by creating stages of builds, all in a single Dockerfile. Just run docker build once.
Here we have three stages.
We can name the stages and reference them later, using only what we need as we move on from stage to stage. You can also stop the build at a specific stage, or even use an external image as a stage. Docker's excellent documentation provides the details.
FROM alpine:latest as stage1
RUN apk add package1
FROM stage1 as stage2
COPY my_service_test.py my_service.py
RUN ...
FROM stage2 as stage3
COPY ...
RUN ...
We can name the stages and reference them later, using only what we need as we move on from stage to stage. You can also stop the build at a specific stage, or even use an external image as a stage. Docker's excellent documentation provides the details.
No comments:
Post a Comment