DEV Community


Posted on

Distroless Alpine

In my day job, we've been using Google's Distroless images for some time. The benefits of this are well known: smaller image and attack surface. However, what we didn't expect is to still to have to deal with a significant amount of toil dealing with vulnerability triage (see Snyk output below for distroless/base). It could be argued our SDLC is a little, clunky and we're not quite ready for scratch (Graal, Golang, etc.,) images yet so what can we do in the interim? 🤔

That lead me to think about a distroless Alpine Linux image. A quick google shows I'm not the only one as a recent Medium article attests. But as we're mostly dealing with Java to get a working image by pulling library-by-library is somewhat of a faff. Fortunately, APKO to the rescue.

APKO is a tool to create lean images using Alpine with only the stuff we need.


At time of writing an Alpine 3.15 image was 5.57MB. Pretty small but still includes some things we don't need, such as sh shell. So with the help of the examples from APKO I came up with:

  - musl
  - zlib

  - groupname: nonroot
    gid: 10000
  - username: nonroot
    uid: 10000
  run-as: nonroot

  version-id: '3.15'  # defaults to 3.16/edge
Enter fullscreen mode Exit fullscreen mode

A few things to note here:

  • Using 3.15 repos, rather than edge used in the examples,
  • Adding a few packages:
    • musl: Needed for pretty much everything,
    • zlib: Required for JRE 17, crashes without it.
  • Using non-root user.
PS ...> docker run --rm `
  -v $pwd/:/app:rw `
  -w /app `
  build rootless.yaml alpine:3.15-apko apko.tar
2022/05/10 09:21:44 loading config file: rootless.yaml
2022/05/10 09:21:45 apko (x86_64): building image 'alpine:3.15-apko'
PS ...>  docker load -i .\apko.tar 
Loaded image: alpine:3.15-apko
Enter fullscreen mode Exit fullscreen mode

The result is a very small image:

REPOSITORY   TAG               IMAGE ID       CREATED         SIZE
alpine       3.15              0ac33e5f5afa   4 weeks ago     5.57MB
alpine       3.15-apko         5a3ea808f8ed   52 years ago    709kB
Enter fullscreen mode Exit fullscreen mode

That's nearly 1/8th of the size (12.7%) and a grand total of just 2 packages (down from 14):

PS ...> docker scan alpine:3.15-apko

Testing alpine:3.15-apko...

Package manager:   apk
Project name:      docker-image|alpine
Docker image:      alpine:3.15-apko
Platform:          linux/amd64

 Tested 2 dependencies for known vulnerabilities, no vulnerable paths found.
Enter fullscreen mode Exit fullscreen mode

That's much smaller than roughly equivalent distroless/base:

REPOSITORY               TAG       IMAGE ID       CREATED        SIZE   nonroot   555ca12a9222   52 years ago   20.3MB
Enter fullscreen mode Exit fullscreen mode

That's over 28x larger and that does have potential issues:

PS ...> docker scan


Package manager:   deb
Project name:      docker-image|
Docker image:
Platform:          linux/amd64

Tested 6 dependencies for known vulnerabilities, found 11 vulnerabilities.
Enter fullscreen mode Exit fullscreen mode

I've trialled my new image with an existing project via JLink that's heavy on Netty and gRPC the image works great (with a small tweak to exclude grpc-netty-shaded due to grpc-java#9083).

What about Java?

Ok, so I don't want to use a JLink minimal JRE, what the difference between a Java 17 JRE:

REPOSITORY                          TAG         IMAGE ID       CREATED        SIZE   nonroot     678ed8ce3ba5   52 years ago   231MB
alpine                              jre17-apko  d2302101850c   52 years ago   202MB
Enter fullscreen mode Exit fullscreen mode

29MB less, that's what!


So, we can have a distroless Alpine image, that's even smaller than Google's with a smaller attack surface. 🔥

The maintainers of APKO highlight it's not released yet and liable to change, but it's a great start.

Top comments (1)

thecleaner profile image

Two things:

  1. apko works perfectly as a GCP CloudBuilder.

  2. if you include the package "alpine-release", you get no complaints from the security scanners.