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 đ