24 Sep

If you build containers Alpine Linux is your friend

Every container image must start from a parent image or base image (the scratch). The parent image is the image you base your image on. The base image is like a completely empty container you need to fill with content. But in most cases, you will use another image as a parent, and you want it to be as minimal as possible. The Alpine Linux is your friend – remember this name and use it as much as possible.

When you build the image from the scratch you first need to apply root filesystem and essential libraries. Comparing multiple minimal Linux distributions we can easily notice they differ in what authors think of “minimal”. Sometimes it includes the tools the author uses, another time it depends on what the distribution is profiled for. One such example is the VMware Photon OS I described in my previous post “Why I use VMware Photon OS for Docker“. The minimal installation has only the essentials required to run the Docker and whole configuration and the kernel are hardened for containers security by default.

When you build the Docker image you want it to be small and secure. To achieve both goals you need to start from scratch and create the image with only required packages or use the base image with minimal setup. The Alpine Linux is a security-oriented, lightweight Linux distribution. It bases on musl libc and busybox so it fits perfectly in those requirements. There are several versions of Alpine Linux – you should use the mini root filesystem for your containers or just refer to alpine in the FROM definition. It is good practice to append the image tag with “-alpine” if the base image was Alpine Linux.

It is all about the security

The fewer packages you use to build the container image the better for the security. Any additional package increases the risk of containing the vulnerability that may put our application or infrastructure on risk. It also means the container will use more disk space and memory. Base images from well-known distributions contain quite many libraries by default. Official Ubuntu 18.04 image size is 84MB, Centos size is 200MB, Debian 101MB while Alpine is only 4.4MB. We get the base image os system with almost nothing and have full control of what we install to fulfill requirements of our application. 

Let me show you an example from the real world. Take a moment to get back to my older post where I described how to automate the process of building Docker image of Jenkins. If you looked at official Jenkins repository into the Dockerfile you could see:

FROM openjdk:8-jdk

If you dig deeper and deeper you will find that everything has been build on top of ubuntu:cosmic image which size is 70MB. Alternatively, you can use the Dockerfile-alpine to build the Jenkins image and put everything on top of the Alpine Linux. Using those two configuration files I created two images that contain base Jenkins installation extended by Docker, Ansible and Robot Framework including all required additional libraries for those applications.

First, let’s look at the size. The Alpine-based image is 40% thinner in size than Centos-based one. There is no magical data compression, it is just not packed with unused packages.

The confirmation is in security scan – Alpine based image consists of 113 packages versus 257 in Centos-based build. The direct result is visible in a number of found known vulnerabilities. 

Building the image on top of Alpine requires much more work on installing the all dependency in libraries, but it worth spending the time – security should always be a top priority. 

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.