Size matters, but it is not all about the size
If you are familiar with Docker, and have been using Docker for some time, you will probably already know or have read, that it is important and a good practice to reduce as much as you can the size of your images. Crafting your Dockerfile carefully to reduce the number of layers, using a minimalist base image to create small images, etc.
Sure, this is very important in order to save some space on disk. It will also reduce the network traffic, since at some point you will upload your image to some registry, to later download to a particular node or nodes. And sure, the startup time of your container could drastically be affected by bigger images, not because it really takes more time to spin up the container of a bigger image, but because if the image is not cached locally, it will need to be downloaded.
So, size matters, but after all, disk memory and network traffic, nowadays are cheap and probably not a big deal or concern. Now, reducing the size of your images, also means reducing content and therefore, security risks. It makes no sense to have an image full of libraries, applications, etc that your applications don’t need. The more “stuff” you have in your image, the more often you will need to update your images to apply security patches and updates, and consequently, redeploy the containers that use them. This also reduces the noise caused by security scanners, which in the majority of the cases, unless your application has been flagged with some CVE or something similar, these security vulnerabilities are not related to your application. Not that your application is not vulnerable though… but that’s a different story.
Having all this extra “stuff” in your image is also a great benefit for an attacker. If a bad actor is able to break into your application, remember is not about if you have been compromised, but when, ideally you have setup your environment to reduce the risks. Using regular Linux commands and applications, can provide many different ways to escape your current shell, escalate privileges, upload/download files, etc. Things like apt-get that we all use to install the dependencies in our image, can be abused, the command more, or something as “innocent” as whois can be abused to upload or download files. Take a look to a project called GTFOBins, it is full of crazy tricks you can do with regular Linux commands.
As much as possible, don’t focus to just reduce the size of your images, but also their content. Try remove as much as you don’t need to mitigate the security risks as well.
“Distroless” images contain only your application and its runtime dependencies. They do not contain package managers, shells or any other programs you would expect to find in a standard Linux distribution.
These images are programming language oriented (Java, Python, NodeJs, etc), and as you can read, they only contain the dependencies your application needs to run. They don’t even contain a shell. Although for debugging purposes, each of the images has a :debug tag, which will add a shell to your image, that will allow you to peek inside your container to debug potential issues during the development phase. Go and read more about that project because is very interesting.
If you prefer, here is a presentation video about the Distroless project: