This is the 26th day of my participation in the Gwen Challenge.More article challenges

Today, using containers for application development and deployment is very common.

While containers provide a lot of value, they also present some challenges, such as:

  • Larger mirrors mean increased build time, as well as increased overhead
  • The more libraries the image contains, the more the vulnerability scanning tool needs to scan

And so on.

The most common solution to this problem is to use a smaller Linux distribution as the base image!

Using a lightweight distribution like Alpine is a very common technique among developers to avoid making container images too big. But there is always the risk of opening vulnerabilities in the underlying library.

Google solved this problem by introducing Distroless mirroring.

The Distroless image contains only your application and its runtime dependencies. They don’t contain package managers, shells, or any other programs you’d expect to find in a standard Linux distribution.

After reading Gaurav Agarwal’s story on how to enhance your container with Distroless container images, I decided to give it a try and get first-hand experience.

In this article, I’ll create a Java application container using Distroless and Alpine images, respectively, scan for vulnerabilities on them, and compare build times, image sizes, and so on.

So let’s get started.

Use Distroless mirroring

I created a simple Hello World Spring Boot application for this experiment.

First, I created a Dockerfile using the Distroless image, as shown below:

FROM maven:3.5-jdk-8 AS build

COPY src /usr/src/app/src

COPY pom.xml /usr/src/app

RUN mvn -f /usr/src/app/pom.xml clean package

FROM gcr.io/distroless/java:8

ARG DEPENDENCY=/usr/src/app/target/dependency

COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib

COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF

COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app

ENTRYPOINT ["java"."-cp"."app:app/lib/*"."DemoApplication.Application"]
Copy the code

The construction is complete, as shown below:

Then I scanned the image with Trivy, and the result is as follows:

Using Alpine Mirror

Next, I repeated the experiment using the Alpine mirror. The Dockerfile for this experiment looks like this:

FROM maven:3.5-jdk-8 AS build

COPY src /usr/src/app/src

COPY pom.xml /usr/src/app

RUN mvn -f /usr/src/app/pom.xml clean package

FROM openjdk:8-jre-alpine

ARG DEPENDENCY=/usr/src/app/target/dependency

COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib

COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF

COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app

ENTRYPOINT ["java"."-cp"."app:app/lib/*"."DemoApplication.Application"]
Copy the code

Build completed successfully:

I then Trivy scanned the mirror image, and the result is shown below:

A direct comparison

Based on this experiment, this is what was observed in my environment:

  • Image size – The image size built using Alpine as the base image is 93.5 MB, while disroless is 139 MB. So Alpine mirroring is much lighter than Disroless mirroring.
  • Number of bugs – Alpine Mirror has 216 bugs (Unknown: 0, Minor: 106, Medium: 79, Critical: 27, Critical: 4), distroless Mirror has 50 bugs (Unknown: 0, Minor: 30, Medium: 6, Critical: 9, Critical: 5)

conclusion

Finally, if you’re more concerned with security, Distroless mirroring is definitely recommended. If you’re worried about mirror size, Alpine might be a better choice.

The experimental code

Here you can find the complete code of the experiment: deshpandetanmay/distroless.

The original link

Which Container Images To Use — Distroless Or Alpine?