What is a chicken? An introduction to distroless containers

Inácio Bueno - Oct 30 - - Dev Community

I’d like to begin this article with a well known story amongst philosophers students, it goes something like: “When Plato gave Socrates' definition of man as "featherless bipeds" and was much praised for the definition, Diogenes plucked a chicken and brought it into Plato's Academy, saying, "Behold! I've brought you a man."

Asking google what is a container, we get the following definition coming from docker (https://www.docker.com/resources/what-container/):A Docker container image is a lightweight, standalone, executable package of software that includes everything needed to run an application: code, runtime, system tools, system libraries and settings”. I don’t think it’s a bad definition, but we know that there are a lot of chickens in it.

And now the big question from this article: What is needed to run an application? Let’s go to the terminal:

Image description

So, I ran a container, specifically the aspnet runtime 8, listed some directories inside, used a command to write from 1 to 10, and then check the size of etc/; if you’re following along, you already know what I’m about to ask you: Why can I do all of those things? And you might say “I don’t know I have ADHD, I was already on instagram/tiktok sending videos to my friends; I got lost in the story of the guy who took a chicken to do who knows what ”. Fair point, I could say, but focus! And about the answer, in fact, I don’t know, maybe the ms team was just lazy and don’t really care for what they left there as long as your application runs it’s all fine. And if you’re so worried, do something yourself!
Bash once again:

Image description

Ok, we know where the binary of ls is, so just remove it, test if the application can still run without it and then add a line in our Dockerfile like RUN rm bin/ls. All done! Now you just need to remove all the other useless stuff. Life is beautiful and simple, I don’t get why so many people complain about it. But wait…. What other useless stuff? Can you remove ‘/’? Then you copy your application there and see what works. Right? YES! That's just the thing to do, in fact, do not even test it, do it directly in production. Say to your manager “devops is just a fancy word for easy work, let me handle it”.

Distroless is what we are looking for: a container image that contains only the necessary to run the application AND NOTHING BEYOND THAT. It’s a hard job to do this, google did it first to run Golang applications, and nowadays there are other options to choose from.
Here, let’s try do the same we did with the aspnet runtime container, but now a distroless:

Image description

Did you notice something? We couldn’t even get into the container, and if you are wondering, maybe it is zsh, ash, or sh… But no, we do not have a terminal in this container. If you look into chainguard description for the image cgr.dev/chainguard/aspnet-runtime:latest, you won’t find a terminal listed in the packages, neither you’ll find ls, seq, du…

“But why do all of this work? Our company is doing fine without it”. The main reason: Security. Each package opens a door and it’s not a door to a good place. Let’s see some basic security analysis from these images.
I’ve created 3 versions of the same dockerfile change only the images:

Image description

1.0 is the default image, 3.0 slim version and the 2.0 it’s distroless. (The first noticeable thing is the size, quite smaller. A big image does not mean that it’s bad, as may have heard, the implicit connection is that if your image is big then it contains more packages and thus it may introduce more vulnerabilities. But it’s not always the case.)
Security analysis results using two different tools to analyze them:
Default:

1.0: Total: 78 (UNKNOWN: 0, LOW: 60, MEDIUM: 16, HIGH: 1, CRITICAL: 1)
1.0: 24 vulnerabilities found in 13 packages

Slim:

3.0: Total: 78 (UNKNOWN: 0, LOW: 60, MEDIUM: 16, HIGH: 1, CRITICAL: 1)
3.0: Detected 13 vulnerable packages with a total of 24 vulnerabilities

Distroless:

2.0: Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)
2.0: No vulnerable packages detected

I hope with article you have learned something new, if you have any question message me on linkedin: https://www.linkedin.com/in/inacio88

.