Wir haben folgenden Block in unserem Dockerfile
:
RUN yum -y update
RUN yum -y install epel-release
RUN yum -y groupinstall "Development Tools"
RUN yum -y install python-pip git mysql-devel libxml2-devel libxslt-devel python-devel openldap-devel libffi-devel openssl-devel
Mir wurde gesagt, dass wir diese RUN
Befehle vereinen sollten, um die Anzahl der erstellten Docker-Ebenen zu verringern:
RUN yum -y update \
&& yum -y install epel-release \
&& yum -y groupinstall "Development Tools" \
&& yum -y install python-pip git mysql-devel libxml2-devel libxslt-devel python-devel openldap-devel libffi-devel openssl-devel
Ich bin sehr neu in Docker und nicht sicher, ob ich die Unterschiede zwischen diesen beiden Versionen der Angabe mehrerer RUN-Befehle vollständig verstehe. Wann würde man RUN
Befehle zu einem einzigen zusammenfassen und wann ist es sinnvoll, mehrere RUN
Befehle zu haben ?
docker
dockerfile
Alecxe
quelle
quelle
Antworten:
Ein Docker-Image ist eine verknüpfte Liste von Dateisystemebenen. Jede Anweisung in einer Docker-Datei erstellt eine Dateisystemebene, die die Unterschiede im Dateisystem vor und nach der Ausführung der entsprechenden Anweisung beschreibt. Der
docker inspect
Unterbefehl kann in einem Docker-Image verwendet werden, um die Art der Verknüpfung mit einer Liste von Dateisystemebenen aufzuzeigen.Die Anzahl der in einem Bild verwendeten Ebenen ist wichtig
Dies hat verschiedene Konsequenzen für die Art und Weise, wie Bilder erstellt werden sollen. Der erste und wichtigste Rat, den ich geben kann, ist:
Der Grund dafür ist, dass alle vorherigen Schritte zwischengespeichert werden und die entsprechenden Ebenen nicht immer wieder heruntergeladen werden müssen. Dies bedeutet schnellere Builds und schnellere Releases, was Sie wahrscheinlich wollen. Interessanterweise ist es überraschend schwierig, den Docker-Cache optimal zu nutzen.
Mein zweiter Rat ist weniger wichtig, aber ich finde ihn unter dem Gesichtspunkt der Wartung sehr nützlich:
Ein Dockerfile, das diesen Rat befolgt, würde so aussehen
und so weiter. Der Ratschlag, mehrere Befehle mit zu binden,
&&
hat nur einen begrenzten Umfang. Es ist viel einfacher, mit Skripten zu schreiben, in denen Sie Funktionen usw. verwenden können, um Redundanz zu vermeiden, oder zu Dokumentationszwecken.Leute, die an Vorprozessoren interessiert sind und bereit sind, den geringen Overhead zu vermeiden, der durch die
COPY
Schritte verursacht wird , und die tatsächlich im laufenden Betrieb eine Docker - Datei erzeugen, in der dieSequenzen werden durch ersetzt
wo das
…
ist die Base64-codierte Versionapt_setup.sh
.Mein dritter Rat ist für Leute, die die Größe und die Anzahl der Lagen zu den möglichen Kosten längerer Bauten begrenzen möchten.
Eine Datei, die durch eine Docker-Anweisung hinzugefügt und durch eine spätere Anweisung entfernt wurde, ist im resultierenden Dateisystem nicht vorhanden, wird jedoch in den Docker-Ebenen, die das Docker-Bild in der Konstruktion bilden, zweimal erwähnt. Einmal mit dem Namen und dem vollständigen Inhalt in der Ebene, der sich aus dem Hinzufügen der Anweisung ergibt, und einmal als Löschhinweis in der Ebene, der sich aus dem Entfernen der Anweisung ergibt.
Nehmen wir zum Beispiel an, wir brauchen vorübergehend einen C-Compiler und ein Image und betrachten das
(Ein realistischeres Beispiel wäre, eine Software mit dem Compiler zu erstellen, anstatt nur das Vorhandensein des Compilers mit dem
--version
Flag zu bestätigen.)Das Dockerfile-Snippet erstellt drei Ebenen, von denen die erste die vollständige gcc-Suite enthält, sodass die entsprechenden Daten, auch wenn sie nicht im endgültigen Dateisystem vorhanden sind, immer noch Teil des Images sind und bei jedem Herunterladen, Hochladen und Entpacken der heruntergeladen werden müssen endgültiges Bild ist.
Das
with
-idiom ist eine gebräuchliche Form in der funktionalen Programmierung, um den Ressourcenbesitz und die Ressourcenfreigabe von der Logik, die es verwendet, zu isolieren. Es ist einfach, diese Redewendung auf Shell-Scripting zu übertragen, und wir können die vorherigen Befehle als das folgende Script umformulieren, dasCOPY & RUN
wie in Hinweis 2 verwendet wird.Komplexe Befehle können in Funktionen umgewandelt werden, so dass sie an die weitergeleitet werden können
with_c_compiler
. Es ist auch möglich, Aufrufe mehrererwith_whatever
Funktionen zu verketten, dies ist jedoch möglicherweise nicht sehr wünschenswert. (Unter Verwendung von esoterischeren Funktionen der Shell ist es sicherlich möglichwith_c_compiler
, komplexe Befehle zu akzeptieren, aber es ist in allen Aspekten vorzuziehen, diese komplexen Befehle in Funktionen zu verpacken.)Wenn wir den Ratschlag Nr. 2 ignorieren möchten, würde das resultierende Dockerfile-Snippet lauten
was wegen der Verschleierung nicht so einfach zu lesen und zu warten ist. Sehen Sie, wie die Shell-Skript-Variante den wichtigen Teil
gcc --version
heraushebt, während die verkettete&&
Variante diesen Teil mitten im Rauschen vergräbt.quelle
Jede Anweisung, die Sie in Ihrem Dockerfile erstellen, führt dazu, dass eine neue Bildebene erstellt wird. Jede Ebene enthält zusätzliche Daten, die nicht immer Teil des resultierenden Bildes sind. Wenn Sie beispielsweise eine Datei in einer Ebene hinzufügen, diese aber später in einer anderen Ebene entfernen, enthält die endgültige Bildgröße die hinzugefügte Dateigröße in Form einer speziellen "Whiteout" -Datei, obwohl Sie sie entfernt haben.
Angenommen, Sie haben das folgende Dockerfile:
Die resultierende Bildgröße ist
Im Gegensatz dazu mit "ähnlichem" Dockerfile:
Die resultierende Bildgröße ist
Sie werden noch kleiner, wenn Sie den YUM-Cache in einer einzigen RUN-Anweisung bereinigen.
Sie möchten also das Gleichgewicht zwischen Lesbarkeit / Wartungsfreundlichkeit und Anzahl der Ebenen / Bildgröße halten.
quelle
Die
RUN
Aussagen repräsentieren jeweils eine Schicht. Stellen Sie sich vor, Sie laden ein Paket herunter, installieren es und möchten es entfernen. Wenn dreiRUN
Anweisungen verwendet werden, wird die Bildgröße nicht verkleinert, da separate Ebenen vorhanden sind. Wenn man alle Befehle mit einerRUN
Anweisung ausführt, kann die Größe des Disk-Image reduziert werden.quelle