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
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.