Om de footprint van een dockerfile klein te houden, is er de mogelijkheid om de zogenaamde multi-stage-build te gebruiken. Bijvoorbeeld om eerst met een Ubuntu image een go applicatie te builden en deze dan daarna uit te voeren met de veel kleinere alpine.
Een initiele Dockerfile zou er zo uit kunnen zien:
FROM ubuntu:22.04 ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y golang-go RUN useradd -m appuser COPY app.go /home/appuser/ USER appuser WORKDIR /home/appuser RUN CGO_ENABLED=0 go build app.go CMD ["/home/appuser/app"]
En als we die builden en dan de grootte van de image bekijken:
$ docker build -t app1 . $ docker image ls | grep app1 app1 latest 9e658b8c6e35 17 seconds ago 654MB
De grootte van de 654MB bevat dus ook allerlei binaries die niet nodig zijn om de go-app uit te voeren. Een multi-stage-build Dockerfile ziet er dan zo uit:
FROM ubuntu:20.04 AS build ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y golang-go=2:1.13~1ubuntu2 COPY app.go . RUN pwd RUN CGO_ENABLED=0 go build app.go FROM alpine:3.12.0 RUN chmod a-w /etc RUN addgroup -S appgroup && adduser -S appuser -G appgroup -h /home/appuser RUN rm -rf /bin/* COPY --from=build /app /home/appuser/ USER appuser CMD ["/home/appuser/app"]
Deze builden en de image opvragen laat zien dat de grootte slechts 7.71MB is:
$ docker build -t app2 . $ docker image ls | grep app2 app2 latest ad9da6395454 17 seconds ago 7.71MB