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
0 0 votes
Article Rating
Abonnieren
Benachrichtige mich bei
guest
0 Comments
Inline Feedbacks
View all comments