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.
- 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.
- 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.
- 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.
- 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.
- 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.