Building Container Images
Container build Tools
The easiest way to build container images is to use Docker and a Dockerfile. However, since Docker isn't cool anymore, there are some other options that may be worth looking into which will be covered in the following subsections.
Docker
The tried and true method to build container images. However, Docker itself can be a bit resource heavy and requires a daemon to be running on the system.
A container is defined in a Dockerfile and built with the docker build
command.
BuildKit
BuildKit is a new code base for building containers that's been part of Docker since version 19.03. It supports some interesting features such as more efficient caching, concurrent dependency resolution, and distributed workers, among other things. A container build is typically faster because of these performance enhancements. Best of all, it uses the same Dockerfile format as Docker.
A container build can be done right now by export the DOCKER_BUILDKIT=1
environment variable while calling docker build
.
Buildah
Buildah is the container building component of podman, Red Hat's replacement to Docker. Containers are built with Dockerfiles (though not all features are supported) using the the podman build
command.
Container build tips
Review the Dockerfile best practices at https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
RUN commands
Try to bundle multiple RUN commands together to reduce the number of container image layers and their overall size. Concatenating multiple commands with &&
or ;
(with set-x,
which stops the script when a non zero exit code is returned).
RUN set -ex; \
yum -y install vim; \
yum clean all
## or,
RUN yum -y install vim && yum clean all
Remember to clean up at the end of each RUN to minimize the layer sizes. Things you can do include:
rm -rf /tmp/* /var/cache/* /var/tmp/*
- Clean up package manager caches and remove unnecessary build-only packages
Better yet, use multi-staged builds (https://docs.docker.com/develop/develop-images/multistage-build/) to bundle the results of multiple layers into one.
FROM centos:8 as build
RUN yum -y update
RUN yum -y install vim
FROM centos:8
## We can copy specific artifacts from the build container. Eg:
COPY --from=build /usr/bin/vim /usr/bin/vim
Yum/dnf-based package managers
Yum or dnf package managers are used on Red Hat based distros.
- Install packages with
yum -y install
to avoid prompts - At the end of the run,
yum -y clean all
, and clean up cachesrm -rf /var/cache
afterwards
Apt-based package managers
Apt-based package managers are used on Ubuntu and Debian based distros.
- Prepend your apt install command with
DEBIAN_FRONTEND=noninteractive
to prevent some packages from prompting interactive input (tzdata
for example), which leads to indefinite waiting for an user input. Don't set this as an environment variable since it will linger after the container is built. - At the end of the run,
rm -rf /var/lib/apt/lists/*
to clean up.
apk-based package managers
Alpine Linux uses the apk package manager. One neat feature with apk is the ability to group packages into virtual groups which we can uninstall with one command.
- Create virtual groups for build dependencies using
apk add --virtual=build-deps make gcc
. These groups can later be removed withapk del --purge build-deps
. - At the end of the run,
/var/cache/apk/*
to clean up.