Ich habe gelesen, dass docker mit Layern arbeitet. Wenn Sie also ein container
mit einem Dockerfile
erstellen, beginnen Sie mit dem Basisimage. Wenn nachfolgende Befehle ausgeführt werden, fügen Sie dem Container eine Ebene hinzu, wenn Sie den Status speichern neuer Container, du hast ein neues Image. Es gibt ein paar Dinge, über die ich mich wundere.
Wenn ich von einem Ubuntu
image aus anfange, das ziemlich groß und sperrig ist, da es ein komplettes OS ist, dann füge ich ein paar Werkzeuge hinzu und speichere es als neues Bild, das ich auf den Hub hochlade. Wenn jemand mein Bild herunterlädt und sie bereits ein Ubuntu-Bild in ihrem images folder
gespeichert haben, bedeutet das, dass sie den Download von Ubuntu
überspringen können, da sie das Bild bereits haben? Wenn ja, wie funktioniert das, wenn ich Teile des Originalbilds modifiziere, verwendet Docker seine zwischengespeicherten Daten, um diese Änderungen nach dem Laden selektiv auf Ubuntu image
anzuwenden?
2.) Wie aktualisiere ich ein Bild, das ich durch Ändern der Dockerfile erstellt habe? Ich habe ein einfaches Django-Projekt mit diesem Dockerfile
:
und verwendet dies, um das Bild am Anfang zu erstellen. Jedes Mal, wenn ich eine Box erstelle, werden alle diese environment variables
geladen. Wenn ich die Box komplett neu anlege, werden die Pakete und alle Extras neu installiert. Ich muss eine neue Umgebungsvariable hinzufügen, also habe ich sie am unteren Rand von Dockerfile
zusammen mit einer Testvariablen hinzugefügt:
Wenn ich den Container und das Bild lösche und einen neuen Container erstelle, scheint alles entsprechend zu gehen, es sagt mir, dass es den neuen Schritt 4: ENV
erstellt %Vor% Bei einigen dieser Zwischen-Container-Übergänge ist es also etwas verloren. Funktioniert das Caching-System, ist jede neue Ebene ein intermediate container
? Wenn Sie also eine neue Ebene hinzufügen, müssen Sie die neuen Daten immer am Ende der Docker-Datei hinzufügen. Oder wäre es besser, die Dockerfile in Ruhe zu lassen, sobald das Image erstellt wurde, und einfach das container
zu modifizieren und ein neues Image zu erstellen?
BEARBEITEN Ich habe gerade versucht, ein Image zu installieren, ein Paket namens bwawrik/bioinformatics
, das ein CentOS-basierter Container ist, der eine Vielzahl von Tools installiert hat.
Es erstarrte halb, also verließ ich es und fuhr es dann erneut, um zu sehen, ob alles installiert war:
%Vor%Also hat es definitiv das Paket in Stücke eingebaut, nicht alles auf einmal. Sind diese Stücke unterschiedliche Bilder?
Lassen Sie mich zuerst einige Begriffe erläutern.
image : Ein statisches, unveränderliches Objekt. Dies ist die Sache, die Sie erstellen, wenn Sie docker build
mit Dockerfile
ausführen. Ein Bild ist keine laufende Sache.
Bilder bestehen aus Ebenen. Ein Bild hat möglicherweise nur eine Ebene oder viele Ebenen.
container : Eine laufende Sache. Es verwendet ein Bild als Startvorlage.
Dies ist vergleichbar mit einem Binärprogramm und einem Prozess. Sie haben ein Binärprogramm auf dem Datenträger (z. B. /bin/sh
), und wenn Sie es ausführen, handelt es sich um einen Prozess auf Ihrem System. Dies ist vergleichbar mit der Beziehung zwischen Bildern und Containern.
Sie können Ihr eigenes Bild aus einem Basisbild erstellen (z. B. ubuntu
in Ihrem Beispiel). Einige Befehle in Dockerfile
erstellen eine neue Ebene im endgültigen Bild. Einige davon sind RUN
, COPY
und ADD
.
Die allererste Ebene hat keine übergeordnete Ebene. Aber jede andere Ebene hat eine übergeordnete Ebene. Auf diese Weise verbinden sie sich miteinander und stapeln sich wie Pfannkuchen.
Jede Ebene hat eine eindeutige ID (die langen hexadezimalen Hashes, die Sie bereits gesehen haben). Sie können auch benutzerfreundliche Namen haben, die als Tags bekannt sind (z. B. ubuntu:16.04
).
Technisch gesehen ist jede Ebene auch ein Bild. Wenn Sie ein neues Bild erstellen und es über 5 Ebenen verfügt, können Sie dieses Bild verwenden und es enthält alle 5 Ebenen. Wenn Sie einen Container mit der dritten Ebene im Stapel als Ihre Bild-ID ausführen, können Sie das auch tun - aber es würde nur 3 Ebenen enthalten. Der eine, den Sie angeben, und die zwei, die seine Vorfahren sind.
Der Begriff "Bild" bezieht sich jedoch allgemein auf die Ebene, der ein Tag zugeordnet ist. Wenn Sie docker images
ausführen, werden Ihnen alle Bilder der obersten Ebene angezeigt und die darunter liegenden Ebenen ausgeblendet (Sie können sie jedoch alle mit -a
anzeigen).
Wenn docker build
ausgeführt wird, wird die gesamte Arbeit innerhalb von Containern ausgeführt (natürlich!). Wenn es einen RUN
-Schritt vorfindet, erstellt es einen Container aus der aktuellen obersten Ebene, führt die angegebenen Befehle dort aus, und speichern Sie das Ergebnis als neue Ebene. Dann wird aus dieser neuen Ebene ein Container erstellt, das nächste ... etc.
Die Zwischencontainer werden nur für den Buildprozess verwendet und nach dem Build verworfen.
Sie haben gefragt, ob jemand, der Ihr ubuntu
-basiertes Bild herunterlädt, nur einen partiellen Download macht, wenn sie das ubuntu
Image bereits lokal hatten.
Ja! Das stimmt genau.
Jede Ebene verwendet die darunter liegende Ebene als Basis. Die neue Ebene ist im Grunde ein Unterschied zwischen dieser Ebene und einem neuen Zustand. Es ist kein Unterschied auf die gleiche Weise wie ein Git Commit funktionieren könnte. Es funktioniert auf Dateiebene, nicht auf Zeilenebene.
Angenommen, Sie haben mit ubuntu
begonnen und diese Docker-Datei ausgeführt.
Dies würde zu einem zweischichtigen Bild führen. Die erste Ebene wäre das Bild ubuntu
. Die zweite hätte wahrscheinlich nur eine Handvoll Veränderungen.
/etc/passwd
mit dem Benutzer "dan" /etc/group
mit der Gruppe "dan" /home/dan
/home/dan/.bashrc
Und das ist es. Wenn Sie einen Container aus diesem Bild starten, befinden sich diese wenigen Dateien in der obersten Ebene und alles andere würde aus dem Dateisystem in ubuntu
image stammen.
Ein anderer Punkt. Wenn Sie einen Container ausführen, können Sie Dateien in das Dateisystem schreiben. Wenn Sie jedoch den Container stoppen und einen anderen Container aus demselben Image ausführen, wird alles zurückgesetzt. Wo werden die Dateien geschrieben?
Bilder sind unveränderlich, sobald sie existieren, können sie nicht mehr geändert werden. Sie können eine neue Version erstellen, aber das ist ein neues Bild. Es hätte eine andere ID und wäre nicht das gleiche Bild.
Ein Container hat eine Lese- / Schreibschicht der obersten Ebene, die auf die Bildschichten gelegt wird. Alle Schreibvorgänge passieren in dieser Ebene. Es funktioniert genau wie die anderen Ebenen. Wenn Sie eine Datei ändern müssen (oder eine Datei hinzufügen oder löschen), geschieht dies in der obersten Ebene und betrifft nicht die unteren Ebenen. Wenn die Datei bereits vorhanden ist, wird sie in die Lese-Schreib-Ebene kopiert und dann geändert. Dies wird als Copy-on-Write (CoW) bezeichnet.
Müssen Sie am Ende von Dockerfile neue Dinge hinzufügen? Nein, Sie können überall etwas hinzufügen (oder etwas ändern).
Wie Sie jedoch Dinge tun, wirkt sich auf Ihre Build-Zeiten aus, weil das Build-Caching funktioniert.
Docker versucht, die Ergebnisse während der Erstellung zwischenzuspeichern. Wenn es beim Lesen durch Dockerfile findet, dass die FROM
gleich ist, ist die erste RUN
die gleiche, die zweite RUN
ist die gleiche ... es wird davon ausgegangen, dass sie diese Schritte bereits ausgeführt hat und verwenden wird Zwischengespeicherte Ergebnisse.Wenn es auf etwas trifft, das sich von dem letzten Build unterscheidet, wird der Cache ungültig. Von diesem Zeitpunkt an wird alles neu ausgeführt.
Manche Dinge werden den Cache immer ungültig machen. Wenn Sie beispielsweise ADD
oder COPY
verwenden, wird der Cache immer ungültig. Das liegt daran, dass Docker nur verfolgt, was die Build-Befehle sind. Es versucht nicht herauszufinden, "ist diese Version der Datei, die ich die gleiche Kopie wie letztes Mal kopiere?"
Es ist also üblich, mit FROM
zu beginnen und dann sehr statische Dinge wie RUN
-Befehle, die Pakete mit z. apt-get
, usw. Diese Dinge ändern sich meist nicht, nachdem Ihre Docker-Datei ursprünglich geschrieben wurde. Später in der Datei ist ein bequemer Ort, um Dinge, die sich häufiger ändern, zu setzen.
Es ist schwierig, dazu einen guten Rat zu geben, weil es wirklich auf das jeweilige Projekt ankommt. Aber es lohnt sich zu lernen, wie das Build-Caching funktioniert und versuchen, es auszunutzen.
Tags und Links docker docker-compose