Use Multi-Stage Builds to Inject CA Certs

Docker’s multi-stage builds are a nice-to-have since so many other packaging workflows developed in their absence. But I thought I’d start introducing people to them with a few practical examples.

Anyone using a language capable of producing statically linked binaries has the opportunity to package based on “scratch” (the empty image). There are quite a few reasons to do this:

  • avoid obscure licensing issues
  • reduced attack surface
  • explicit dependency management

However one constant pain is dealing with CA root certificates. Images based on an image like alpine can use built in package management to fetch updated CA certificates provided by the distribution. There is no package management for scratch. You have to bring your own CA certificate bundle.

Multi-stage builds make it easier to borrow automations and artifacts from other images. The example below uses the alpine package manager to fetch the current ca-certificates package and later copy the downloaded artifact into a different image based on scratch.

FROM alpine:latest as certs
RUN apk --update add ca-certificates
FROM scratch
ENV PATH=/bin
COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
# COPY ./bin/<YOUR BINARY HERE> /bin/<YOUR BINARY HERE>
# Do your standard packaging work...

If you haven’t had the chance to get your hands dirty with multi-stage builds maybe a little gem like this one will give you a good excuse to do so.

Show your support

Clapping shows how much you appreciated Jeff Nickoloff’s story.