Kurzum: Nein, Ihre VOLUME
Anweisung ist nicht korrekt.
Docker-Dateien VOLUME
geben ein oder mehrere Volumes an, wenn container-seitige Pfade angegeben sind. Der Bildautor kann jedoch keinen Hostpfad angeben. Auf der Hostseite werden die Volumes mit einem sehr langen ID-ähnlichen Namen im Docker-Stammverzeichnis erstellt. Auf meiner Maschine ist das /var/lib/docker/volumes
.
Hinweis: Da der automatisch generierte Name extrem lang ist und aus menschlicher Sicht keinen Sinn ergibt, werden diese Bände häufig als "unbenannt" oder "anonym" bezeichnet.
Ihr Beispiel, das ein '.' Das Zeichen wird nicht einmal auf meinem Computer ausgeführt, egal ob ich den Punkt zum ersten oder zweiten Argument mache. Ich erhalte diese Fehlermeldung:
Docker: Fehlerantwort vom Daemon: oci Laufzeitfehler: container_linux.go: 265: Start des Containerprozesses verursacht "process_linux.go: 368: container init verursacht" open / dev / ptmx: keine solche Datei oder kein solches Verzeichnis ".
Ich weiß , dass nicht sehr wertvoll ist wohl jemand zu diesem Punkt gesagt , was hat versucht , zu verstehen , VOLUME
und -v
und es bietet sicherlich keine Lösung für das, was Sie versuchen zu erreichen. Hoffentlich werden die folgenden Beispiele mehr Licht in diese Fragen bringen.
Minitutorial: Festlegen von Volumes
Angesichts dieser Docker-Datei:
FROM openjdk:8u131-jdk-alpine
VOLUME vol1 vol2
(Für das Ergebnis dieses Minitutoriums spielt es keine Rolle, ob wir angeben vol1 vol2
oder /vol1 /vol2
- fragen Sie mich nicht warum)
Baue es:
docker build -t my-openjdk
Lauf:
docker run --rm -it my-openjdk
Führen Sie ls
im Container die Befehlszeile aus, und Sie werden feststellen, dass zwei Verzeichnisse vorhanden sind. /vol1
und /vol2
.
Durch Ausführen des Containers werden auch zwei Verzeichnisse oder "Volumes" auf der Hostseite erstellt.
Wenn der Container ausgeführt wird, führen Sie ihn docker volume ls
auf dem Host-Computer aus, und Sie werden Folgendes sehen (der Kürze halber habe ich den mittleren Teil des Namens durch drei Punkte ersetzt):
DRIVER VOLUME NAME
local c984...e4fc
local f670...49f0
Zurück im Container ausführen touch /vol1/weird-ass-file
(erstellt eine leere Datei an dieser Stelle).
Diese Datei ist jetzt auf dem Host-Computer in einem der unbenannten Volumes verfügbar. Lol. Ich habe zwei Versuche gebraucht, weil ich zuerst das erste aufgelistete Volume ausprobiert habe, aber schließlich habe ich meine Datei mit dem folgenden Befehl auf dem Host-Computer im zweiten aufgelisteten Volume gefunden:
sudo ls /var/lib/docker/volumes/f670...49f0/_data
Ebenso können Sie versuchen, diese Datei auf dem Host zu löschen, und sie wird auch im Container gelöscht.
Hinweis: Der _data
Ordner wird auch als "Einhängepunkt" bezeichnet.
Beenden Sie den Container und listen Sie die Volumes auf dem Host auf. Sie sind weg. Wir haben das --rm
Flag beim Ausführen des Containers verwendet und diese Option löscht nicht nur den Container beim Beenden, sondern auch die Volumes.
Führen Sie einen neuen Container aus, geben Sie jedoch ein Volume an, indem Sie -v
:
docker run --rm -it -v /vol3 my-openjdk
Dies fügt ein drittes Volume hinzu und das gesamte System verfügt über drei unbenannte Volumes. Der Befehl wäre abgestürzt, wenn wir nur angegeben hätten -v vol3
. Das Argument muss ein absoluter Pfad innerhalb des Containers sein. Auf der Hostseite ist das neue dritte Volume anonym und befindet sich zusammen mit den beiden anderen Volumes in /var/lib/docker/volumes/
.
Es wurde bereits erwähnt, dass das Dockerfile
nicht einem Hostpfad zugeordnet werden kann, was für uns ein Problem darstellt, wenn wir versuchen, zur Laufzeit Dateien vom Host in den Container zu bringen. Eine andere -v
Syntax löst dieses Problem.
Stellen Sie sich vor, ich habe einen Unterordner in meinem Projektverzeichnis ./src
, mit dem ich /src
im Container synchronisieren möchte . Dieser Befehl macht den Trick:
docker run -it -v $(pwd)/src:/src my-openjdk
Beide Seiten des :
Charakters erwarten einen absoluten Pfad. Die linke Seite ist ein absoluter Pfad auf dem Host-Computer, die rechte Seite ist ein absoluter Pfad innerhalb des Containers. pwd
ist ein Befehl, der "aktuelles / Arbeitsverzeichnis drucken". Wenn Sie den Befehl $()
eingeben, wird der Befehl in Klammern gesetzt, in einer Unterschale ausgeführt und der absolute Pfad zu unserem Projektverzeichnis zurückgegeben.
Nehmen wir an, wir haben alles ./src/Hello.java
in unserem Projektordner auf dem Host-Computer mit den folgenden Inhalten:
public class Hello {
public static void main(String... ignored) {
System.out.println("Hello, World!");
}
}
Wir erstellen diese Docker-Datei:
FROM openjdk:8u131-jdk-alpine
WORKDIR /src
ENTRYPOINT javac Hello.java && java Hello
Wir führen diesen Befehl aus:
docker run -v $(pwd)/src:/src my-openjdk
Dies druckt "Hallo Welt!".
Das Beste daran ist, dass wir die Java-Datei bei einem zweiten Durchlauf mit einer neuen Nachricht für eine andere Ausgabe ändern können - ohne das Bild neu erstellen zu müssen =)
Schlussbemerkungen
Ich bin ziemlich neu in Docker und das oben erwähnte "Tutorial" spiegelt Informationen wider, die ich aus einem dreitägigen Kommandozeilen-Hackathon gesammelt habe. Ich schäme mich fast, dass ich keine Links zu klaren englischsprachigen Dokumentationen bereitstellen konnte, die meine Aussagen stützen, aber ich denke ehrlich, dass dies auf mangelnde Dokumentation und nicht auf persönlichen Aufwand zurückzuführen ist. Ich weiß, dass die Beispiele mit meinem aktuellen Setup "Windows 10 -> Vagrant 2.0.0 -> Docker 17.09.0-ce" wie angekündigt funktionieren.
Das Tutorial löst nicht das Problem "Wie geben wir den Pfad des Containers in der Docker-Datei an und lassen den Befehl run nur den Hostpfad angeben". Es könnte einen Weg geben, ich habe ihn einfach nicht gefunden.
Schließlich habe ich das Gefühl, dass die Angabe VOLUME
in der Docker-Datei nicht nur ungewöhnlich ist, sondern wahrscheinlich eine bewährte Methode ist, die niemals verwendet wird VOLUME
. Aus zwei Gründen. Der erste Grund, den wir bereits identifiziert haben: Wir können den Hostpfad nicht angeben - was gut ist, da Dockerfiles sehr unabhängig von den Besonderheiten eines Hostcomputers sein sollten. Der zweite Grund ist jedoch, dass die Benutzer möglicherweise vergessen, die --rm
Option beim Ausführen des Containers zu verwenden. Man könnte daran denken, den Behälter zu entfernen, aber vergessen, das Volumen zu entfernen. Selbst mit dem besten menschlichen Gedächtnis kann es eine entmutigende Aufgabe sein, herauszufinden, welche aller anonymen Volumes sicher entfernt werden können.