Docker Container Layer mit Multi-Stage Builds zusammenfassen

Veröffentlicht von

Einige meiner Dockerfiles beinhalten viele RUN und COPY Schritte. Einfaches Beispiel, dass zur Veranschaulichung dient:

FROM    docker.io/rockylinux:8

ARG     VERSION=1.0.0

COPY    FILE1 /etc/FILE1
COPY    FILE2 /etc/FILE2
RUN     /usr/local/sbin/install_script.sh
RUN     rm -f /usr/local/sbin/install_script.sh
RUN     microdnf -y install git-core jq sudo && \
microdnf clean all && \
rm -rf /var/cache/{dnf,yum} && \
rm -rf /var/lib/dnf/history.* && \
rm -rf /var/log/*

Jeder Schritt erzeugt einen neuen Container-Layer und vergrĂ¶ĂŸert das Container-Image. Um das Container-Image zu verkleinern und alle Layer zusammenzufassen, gab es die experimentelle Option docker build --squash=true. Seit einigen Docker-Versionen wird bei Nutzung der Option allerdings folgende Meldung ausgegeben:

WARNING: experimental flag squash is removed with BuildKit. You should squash inside build using a multi-stage Dockerfile for efficiency.

Die squash Option steht uns also nicht mehr zur VerfĂŒgung. Wir können aber mit einem Multi-Stage Build alle Container Layer zu einem Layer zusammenfassen. Ein Multi-Stage Build ermöglicht es, mehrere Build-Stages in einem einzigen Dockerfile zu definieren. Dies ist besonders nĂŒtzlich, um AbhĂ€ngigkeiten zu installieren und Build-Schritte durchzufĂŒhren, ohne den endgĂŒltigen Container mit unnötigem Ballast zu belasten. z.B. lĂ€sst sich ein in GO geschriebenes Projekt im ersten Stage kompilieren und dann das fertig kompilierte Binary aus der ersten Stage in den zweiten Stage kopieren, ohne dabei alle Build AbhĂ€ngigkeiten mitzunehmen. Diesen Mechanismus, Dateien zwischen Stages zu kopieren, können wir nutzen um alle Layer zu einem Layer zusammenzufassen. Beispiel:

FROM    docker.io/rockylinux:8 AS build

ARG     VERSION=1.0.0

COPY    FILE1 /etc/FILE1
COPY    FILE2 /etc/FILE2
RUN     /usr/local/sbin/install_script.sh
RUN     rm -f /usr/local/sbin/install_script.sh
RUN     microdnf -y install git-core jq sudo&& \
microdnf clean all && \
rm -rf /var/cache/{dnf,yum} && \
rm -rf /var/lib/dnf/history.* && \
rm -rf /var/log/*

FROM scratch AS final

COPY --from=build / /


In der ersten Build-Stage werden alle Schritte ausgefĂŒhrt. Anschließend wird das Root-Dateisystem / in die zweite Build-Stage kopiert. Dadurch wird das endgĂŒltige Container Image auf einen einzigen Layer reduziert, anstatt mehrere Layer fĂŒr die einzelnen Schritte des Build-Prozesses zu verwenden.

Das Beispiel beinhaltet es nicht aber falls euer Container z.B. Entrypoints oder Labels haben, mĂŒssen diese im letzten Build-Stage hinzugefĂŒgt werden. Klingt logisch, aber es soll Menschen geben, die beim ersten mal darĂŒber gestolpert sind 🙈

Teile diesen Beitrag

Kommentar hinterlassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert