Docker ADD vs VOLUME


116

Ich lerne Docker und ich habe Zweifel darüber , wann und wo zu verwenden ADDund VOLUME. Ich denke, beide tun Folgendes:

HINZUFÜGEN

Kopieren Sie die Dateien beim Erstellen in das Image. Das Image enthält alle Dateien, sodass Sie es sehr einfach bereitstellen können. Auf der anderen Seite scheint es keine gute Idee in der Entwicklung zu sein, jedes Mal erstellen zu müssen, da der Entwickler beim Erstellen einen Befehl ausführen muss, um den Container neu zu erstellen. Darüber hinaus kann der Bau des Containers zeitaufwändig sein.

VOLUMEN

Ich verstehe, dass docker run -vSie mithilfe eines Host-Ordners in Ihrem Container mounten können. Auf diese Weise können Sie problemlos Dateien ändern und beobachten, wie die App in Ihrem Container auf die Änderungen reagiert. Es sieht in der Entwicklung gut aus, aber ich bin nicht sicher, wie ich meine Dateien auf diese Weise bereitstellen soll.


3
Im Allgemeinen ist es am besten bevorzugen COPYzu ADD. Sie sind fast gleich, ADDverfügen jedoch über einige zusätzliche Funktionen für URLs und Archivdateien, die überraschend sein können.
Adrian Mouat

2
@jamesmstone - dieser Link (und die offiziellen Docker-Dokumente) empfehlen das Gegenteil - verwenden Sie COPY anstelle von ADD.
Software Engineer

Ups, du hast recht - Prost!
Jamesstone

Antworten:


183

HINZUFÜGEN

Der grundlegende Unterschied zwischen diesen beiden besteht darin, ADDdass alles , was Sie hinzufügen, sei es ein Ordner oder nur eine Datei, tatsächlich Teil Ihres Bildes ist . Jeder, der das später erstellte Image verwendet, hat Zugriff auf alles, was Sie tun ADD. Dies gilt auch dann, wenn Sie es anschließend entfernen, da Docker in Ebenen arbeitet und die ADDEbene weiterhin als Teil des Bildes vorhanden ist. Um klar zu sein, Sie haben nur ADDetwas zur Erstellungszeit und können niemals ADDzur Laufzeit.

Einige Beispiele für Fälle, in denen Sie Folgendes verwenden möchten ADD:

  • Sie haben einige Anforderungen in einer Datei "require.txt", auf die Sie verweisen und die Sie in Ihrer Docker-Datei installieren möchten. Sie können dann tun: ADD ./requirements.txt /requirements.txtgefolgt vonRUN pip install -r /requirements.txt
  • Sie möchten Ihren App-Code als Kontext in Ihrer Docker-Datei verwenden. Wenn Sie beispielsweise Ihr App-Verzeichnis als Arbeitsverzeichnis in Ihrem Image festlegen und den Standardbefehl in einem Container ausführen möchten, der von Ihrem Image ausgeführt wird, führen Sie Ihre App tatsächlich aus tun können:

    ADD ./ /usr/local/git/my_app

    WORKDIR /usr/local/git/my_app

    CMD python ./main.py

VOLUMEN

Mit Volume hingegen kann ein Container, der von Ihrem Image ausgeführt wird, nur auf einen Pfad auf dem lokalen Computer zugreifen, auf dem der Container ausgeführt wird. Sie können keine Dateien aus Ihrem VOLUMEVerzeichnis in Ihrer Docker-Datei verwenden . Alles , was in Ihrem Volumen Verzeichnis wird bei Build-Zeit nicht erreichbar sein , sondern wird zur Laufzeit zugänglich sein .

Einige Beispiele für Fälle, in denen Sie Folgendes verwenden möchten VOLUME:

  • Die App, die in Ihrem Container ausgeführt wird, meldet sich an /var/log/my_app. Sie möchten, dass auf diese Protokolle auf dem Hostcomputer zugegriffen werden kann und nicht gelöscht wird, wenn der Container entfernt wird. Sie können dies tun, indem Sie einen Einhängepunkt erstellen, /var/log/my_appindem Sie ihn VOLUME /var/log/my_appzu Ihrer Docker-Datei hinzufügen und dann Ihren Container mit ausführendocker run -v /host/log/dir/my_app:/var/log/my_app some_repo/some_image:some_tag
  • Sie haben einige lokale Einstellungsdateien, auf die die App im Container Zugriff haben soll. Möglicherweise unterscheiden sich diese Einstellungsdateien auf Ihrem lokalen Computer von der Entwicklung oder der Produktion. Besonders dann, wenn diese Einstellungsdateien geheim sind. In diesem Fall möchten Sie sie definitiv nicht in Ihrem Bild haben . In diesem Fall ist es eine gute Strategie VOLUME /etc/settings/my_app_settings, Ihre Docker-Datei zu erweitern, Ihren Container mit auszuführen docker run -v /host/settings/dir:/etc/settings/my_app_settings some_repo/some_image:some_tagund sicherzustellen, dass das Verzeichnis / host / settings / in allen Umgebungen vorhanden ist, in denen Ihre App ausgeführt werden soll.

13
Der mit Abstand nützlichste Beitrag, den ich bisher auf ADD und VOLUME gefunden habe
Jasmeet

5
Was passiert, wenn VOLUME angegeben, aber während des Docker-Laufs nicht angegeben wird (z. B. fehlt der Parameter -v xxx)? Ist die resp. VOLUME wird dann effektiv vorübergehend?
col.panic

In einer Docker-Datei sind Volumes wahrscheinlich nur für die Persistenz und / oder das Debuggen gedacht. Sie können jedoch den Befehlszeilenschalter für Volumes verwenden, um eine App in ein vorhandenes Image zu integrieren (keine Docker-Datei erforderlich) und wie folgt auszuführen docker run -v $HOST_PATH:$CONTAINER_PATH node:latest node $CONTAINER_PATH/app.js.
Chinoto Vokro

schönes "Schicht" Detail
Stratovarius

27

Die VOLUMEAnweisung erstellt zur Laufzeit ein Datenvolumen in Ihrem Docker-Container. Das als Argument angegebene VOLUMEVerzeichnis ist ein Verzeichnis, das das Union-Dateisystem umgeht und hauptsächlich für persistente und gemeinsam genutzte Daten verwendet wird.

Wenn Sie ausführen docker inspect <your-container>, sehen Sie unter dem MountsAbschnitt einen, Sourceder den Verzeichnisspeicherort auf dem Host darstellt, und einen, Destinationder den gemounteten Verzeichnisspeicherort im Container darstellt. Beispielsweise,

"Mounts": [
  {
    "Name": "fac362...80535",
    "Source": "/var/lib/docker/volumes/fac362...80535/_data",
    "Destination": "/webapp",
    "Driver": "local",
    "Mode": "",
    "RW": true,
    "Propagation": ""
  }
]

Hier sind 3 Anwendungsfälle für docker run -v:

  1. docker run -v /data: Dies entspricht der Angabe der VOLUMEAnweisung in Ihrer Docker-Datei.
  2. docker run -v $host_path:$container_path: Auf diese Weise können Sie zur Laufzeit $host_pathvon Ihrem Host $container_pathin Ihren Container mounten . In der Entwicklung ist dies nützlich, um den Quellcode auf Ihrem Host für den Container freizugeben. In der Produktion kann dies verwendet werden, um Dinge wie die DNS-Informationen des Hosts (in /etc/resolv.conf) oder Geheimnisse in den Container zu mounten . Umgekehrt können Sie diese Technik auch verwenden, um die Protokolle des Containers in bestimmte Ordner auf dem Host zu schreiben. Beides $host_pathund $container_pathmüssen absolute Pfade sein.
  3. docker run -v my_volume:$container_path: Dadurch wird ein Datenvolumen in Ihrem Container unter erstellt $container_pathund benannt my_volume. Dies entspricht im Wesentlichen dem Erstellen und Benennen eines Volumes mit docker volume create my_volume. Das Benennen eines solchen Volumes ist nützlich für ein Container-Daten-Volume und ein Shared-Storage-Volume mithilfe eines Multi-Host-Speichertreibers wie Flocker .

Beachten Sie, dass der Ansatz zum Mounten eines Hostordners als Datenvolume in Dockerfile nicht verfügbar ist. Um die Docker-Dokumentation zu zitieren ,

Hinweis: Dies ist in einer Docker-Datei aufgrund der Portabilität und des Freigabezwecks nicht verfügbar. Da das Host-Verzeichnis naturgemäß hostabhängig ist, würde ein in einer Docker-Datei angegebenes Host-Verzeichnis wahrscheinlich nicht auf allen Hosts funktionieren.

Wenn Sie jetzt Ihre Dateien in Container in Nicht-Entwicklungsumgebungen kopieren möchten, können Sie die Anweisungen ADDoder COPYin Ihrer Docker-Datei verwenden. Diese verwende ich normalerweise für die Bereitstellung außerhalb der Entwicklung.


3
Soll ich 2 Docker-Dateien erstellen? Eine für die Entwicklung und eine für die Bereitstellung?
Cristian Garcia

Das glaube ich nicht. Es ist nichts Falsches daran, die ADDAnweisung in Ihrer Docker-Datei zu haben, da sie nur vom docker buildBefehl ausgeführt wird. Dies ist erforderlich, wenn andere Ihren Container zum ersten Mal erstellen und wenn Sie bereit sind, ihn in anderen Nichtentwicklungsumgebungen bereitzustellen.
ivan.sim

3
Aber wäre es nicht effizienter, ein Image ohne die Dateien zu erstellen und den -vBefehl für die Entwicklung zu verwenden, und eine andere Docker-Datei ein Image erstellen zu lassen, das die Dateien ADDfür die Bereitstellung enthält?
Cristian Garcia

1
Es ist ein Kompromiss, den Sie entscheiden müssen. Wählen Sie aus, was für Sie funktioniert. Wie lange dauert der Build mit einem überhaupt ADD? Insgesamt ein paar Sekunden? Wenn Sie zwei Dockerfile-Dateien haben und diese für andere freigeben (oder in der Docker-Registrierung veröffentlichen ), welche ist die Standardeinstellung? Sie haben zusätzlichen Wartungsaufwand, um sicherzustellen, dass die richtige Standard-Docker-Datei die richtigen Benutzer erreicht. Aber am Ende des Tages entscheiden Sie, was für Sie am besten funktioniert. Persönlich möchte ich sicherstellen, dass es nur eine Docker-Datei gibt, um meinen Container zu erstellen.
ivan.sim

11
Übrigens denke ich, dass es in Ordnung ist, zuerst ADD hinzuzufügen und dann das Add-V für die Entwicklung zu überschreiben. Auf diese Weise benötigen Sie keine separaten Docker-Dateien.
Attila Szeremi
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.