Distroless Image in Docker and Kubernetes Environment

Sandeep Kumar
5 min readSep 29, 2022

Introduction

A ‘distroless’ image is just a ‘simple containerized application image’ with slimmed Linux distribution, application runtime and application binary.

Use of ‘Distroless’ images is growing rapidly. There are various reasons being circulated as cause for getting it more popular rapidly. Some of the popular reasons are:

  • enhanced security — Images are considered more secure with distroless with lower attack surface
  • lightweight — The distroless images are slimmed therefore it is lightweight in size
  • cost saving — since size is less, it will require less memory to store which turned to cost saving

There are many developers, architects and organization is advocating for distroless and there are many in oppose. Sharing own experience with distroless with this article.

About Distroless

To run application, at least below components are required:

  • application binary with dependencies — an application may be created by choosing any programming language based on development requirement and capabilities. For example, Java with Spring Framework for creating REST based application
  • runtime — based on the programming language used for application development, runtime is required to run the application
  • operating system (OS) / containerized OS platform — an OS platform is required to host the runtime and application which either may be standalone OS or containerized OS platform based on OS image

But it is fact that when an image is created, it contains not only necessary artifacts/binaries, it contains several unnecessary tools and binaries. Typically, an image looks like:

Figure 1: Typical contents of application image

Now, idea is to remove unnecessary artifacts and binaries to reduce the size of image and improve security.

Let’s understand ‘how removing unnecessary artifacts & binaries will improve security’?

It is very simple, more components will require more code, binaries & functionalities which increase attack surface and changes of high vulnerabilities. In simple words, less code means less effort, less chances to failure, less functionality exposure which can exploit by attackers.

It is too hard to remove unnecessary binaries/artifacts completely from the appli

To reduce the unnecessary artifacts/binaries, there are two ideas:

  • Lightweight Linux Image like Alpine — Alpine Linux distribution is considered one of the lightest Linux distribution which is around 4 MB in size. There are several lightweight Linux distributions are available along with runtime as well
  • Distroless — a distroless is extremely slimmed Linux distribution which contains runtime and application only, nothing else. Google has introduced this term ‘distroless’ and publishing various distroless image for different runtime.

Although, the both concepts are very much same and targeting to same results: lighten the image and decrease attack surface. The size is somehow also associated with loading performance, small size will definitely take less time to boot up.

A distroless image looks like:

Figure 2: A distroless application image

Note: It is important to understand that size does not have direct relationship with security and vulnerabilities. It may be possible that smaller software in size may have more vulnerabilities than a bigger size software which has been written carefully by taking security concerns in mind.

It is also important that security issues are not identified at once. Issues are identified over the time in various situations and exploration so reducing vulnerabilities only linked with how it being fixed.

Use Case

To use distroless, one can use ‘Google published distroless’ images as base image for the application.

There are may such distroless available for different runtime like Java, Python, Go, R etc.

To demonstrate distroless, two examples will be discussed here:

Prerequisite:

  • Docker must be available because docker is being used for creating docker image using distroless based image

Java disroless image

  1. Create a Java file with name HelloJava.java with below content:
package examples;class HelloJava {public static void main(String...args) throws Exception {
System.out.println("Hello Java");
Thread.sleep(2000);
System.out.println("Hello Java - end");
}
}

2. Create a Dockerfile with below contents:

FROM openjdk:11-jdk-slim-bullseye AS build-env
COPY . /app/examples
WORKDIR /app
RUN ls /
RUN javac examples/*.java
RUN jar cfe main.jar examples.HelloJava examples/*.class
# FROM gcr.io/distroless/java11-debian11:latest
FROM gcr.io/distroless/java11-debian11:debug
COPY --from=build-env /app /app
WORKDIR /app
CMD ["main.jar"]

3. Run below command to create docker image:

docker build -t javaapp/hellojava:latest .

4. To run this image run below command:

docker run javaapp/hellojava:latest 

Node distroless image

  1. Create package.json with below contents:
{
"name": "docker_web_app",
"version": "1.0.0",
"main": "server.js",
"dependencies": {
"express": "^4.16.1"
}
}

2. Create server.js with below contents:

const express = require('express')const app = express()
app.get('/', (req, res) => {
res.send('Hello There')
})
app.listen(8080, '0.0.0.0')

3. Create Dockerfile with below contents:

FROM node:10.17.0 AS build-env
ADD . /app
WORKDIR /app
RUN npm install
RUN npm ci --only=production
FROM gcr.io/distroless/nodejs
COPY --from=build-env /app /app
WORKDIR /app
CMD ["server.js"]

4. Run below command to create docker image:

docker build -t nodeapp/server-app:latest .

5. To run this image run below command:

docker run nodeapp/server-app:latest -p 8080:8080

It will start node app on port 8080 which can be tested as curl http://localhost:8080/

These images will not have additional OS and runtime commands and binaries therefore exec will not be running even shell.

You can try below command will fail and will not launch shell:

docker exec -ti nodeapp/server-app:latest /bin/sh

Also, docker image size can be checked by exporting image.

These distroless images can also be deployed in Kubernetes environment without any issue.

Conclusion

Distroless docker images are just way to lighten the application image by removing unnecessary binaries, artifacts and functionalities.

Since unnecessary components are removed, its size will be less and attack surface will be smaller. And there is a chance for reduces vulnerabilities as well.

There are different ways to make application image lighter like using Alpine Linux distributions and similar security benefits can also be achieved with Alpine very easily therefore people are distributed in segments for ‘distroless image benefits and usages’.

May developers, architects, devsecops consider distroless beneficial but many are in oppose of it. Have worked on both type of images and can say there is no difference in both. It just way how we implement nothing else. For each ways (lightweight image and distroless image), similar size and security benefits can be achieved easily.

Additionally, felt that distroless becomes challenging while bug investigation for example, suppose traffic need to be check whether it is landing in Pod or not, it becomes tough when distroless image has been used because it does not have any tool like curl, wget, telnet client etc.

Reference

--

--

Sandeep Kumar

Sandeep Kumar holds Master of Computer Application, working as Technical Architect having 11+ years of working experience in banking, retail, education domains.