TL;DR

If you don’t care about distroless bla-bla and just want to know how to create distroless alpine images, click here

Distroless ?

In a distroless docker image, you won’t find any shell, package manager or utilities such as grep, sed, awk, … It runs only your application and nothing else.

Don’t expect to launch commands like docker run -it my-distroless-image something, it will fail with a message like this one:

standard_init_linux.go:228: exec user process caused: no such file or directory

Why use distroless images ?

From what I read here.

  1. Less attack surface: By avoiding unnecessary stuffs on the packaged docker images, the doors for any kind of attack from inside or outside is reduced. Distroless has no package manager like apk tools in alpine, apt in ubuntu. In case, attacker want to change a live container installing packages, there’s no chance.
  2. Avoid Image Vulnerabilities: Using general OS specific docker images, they need to be updated in case of any vulnerabilities or apply security patches. Also, packages and libraries vulnerability can be avoided to greater extent.
  3. Confirms Immutability: Immutability should be in the heart while running docker container. Even if by chance you are doing manual operation inside docker, the was needs to be left instantly.
  4. Secure Secret Variables: We basically use file based secrets or environment variables. If someone by some way exec into docker container, the secret is clearly exposed but as Distroless doesn’t have shell access.
  5. Secure Network Connection/Service Call: We could have services running in docker which are not exposed to external world but visible to internal network for eg. by using service name in Kubernetes. In case of any unprivileged access, the service call can be easily made from one container to other in the network. Also, for security purpose, we limit database access from inside the container in network which becomes useless if someone gets shell access. Restricting shell access stops this kind of attack surfaces by Distroless.

Google Distroless images

Google has created distroless images but even if they contains no shell or package manager, you will see remaining vulnerabilities if you scan them with a vulnerability scanner, and some of them have a Won’t fix flag:

$ grype gcr.io/distroless/base-debian11
 ✔ Vulnerability DB        [updated]
 ✔ Loaded image
 ✔ Parsed image
 ✔ Cataloged packages      [6 packages]
 ✔ Scanned image           [19 vulnerabilities]
NAME       INSTALLED         FIXED-IN     VULNERABILITY     SEVERITY
libc6      2.31-13+deb11u2                CVE-2021-43396    Negligible
libc6      2.31-13+deb11u2   (won't fix)  CVE-2021-3998     Unknown
libc6      2.31-13+deb11u2   (won't fix)  CVE-2021-3999     Unknown
libc6      2.31-13+deb11u2   (won't fix)  CVE-2022-23218    Critical
libc6      2.31-13+deb11u2   (won't fix)  CVE-2022-23219    Critical
(...etc...)

Google distroless images are only Debian based.

Alpine Linux

Alpine Linux is a security-oriented, lightweight Linux distribution based on musl libc and busybox. If you scan alpine docker images, it will usually return zero vulnerabilities.

$ grype alpine:latest
No vulnerabilities found

Alpine package manager

Alpine package manager is apk.

Busybox

If you have a closer look at Alpine utilities, you will notice they are all symbolic links to busybox.

$ ls -alh /bin/ | head
lrwxrwxrwx    1 root     root          12 Nov 24 09:20 arch -> /bin/busybox
lrwxrwxrwx    1 root     root          12 Nov 24 09:20 ash -> /bin/busybox
lrwxrwxrwx    1 root     root          12 Nov 24 09:20 base64 -> /bin/busybox
lrwxrwxrwx    1 root     root          12 Nov 24 09:20 bbconfig -> /bin/busybox
-rwxr-xr-x    1 root     root      805.6K Nov 23 00:57 busybox
lrwxrwxrwx    1 root     root          12 Nov 24 09:20 cat -> /bin/busybox
lrwxrwxrwx    1 root     root          12 Nov 24 09:20 chgrp -> /bin/busybox

BusyBox is a software suite that provides several Unix utilities in a single executable file.

Create an Alpine distroless image

As Alpine Linux relies on busybox, it is as simple as removing busybox and apk to make Alpine a distroless distro.

Basic Dockerfile example

FROM alpine:latest
RUN apk upgrade --no-cache; \
    # Distroless magic, first remove all busybox symlinks
    find /sbin /bin /usr/bin /usr/local/bin/ -type l  -exec busybox rm -rf {} \;; \
    # then use busybox to remove busybox itself and apk
    busybox rm /sbin/apk /bin/busybox

PHP Dockerfile example

Usually, you will have to inspect how the alpine image is built to make it a distroless one. Find below an example for php alpine image:

FROM php:alpine
RUN apk upgrade --no-cache; \
    # Distroless magic
    find /sbin /bin /usr/bin /usr/local/bin/ -type l  -exec busybox rm -rf {} \;; \
    busybox rm /sbin/apk /bin/busybox
ENTRYPOINT ["/usr/local/bin/php"]

This blog run on a distroless image

This blog is running on a distroless and unprivileged nginx docker image. You will find its Dockerfile by clicking here.