Docker Container Volumes verstehen und verwalten

Erfahren Sie, wie Docker mit Container-Speichervolumes umgeht, wie Sie einen Container mit einem Volume über die Befehlszeile und aus einer Dockerdatei starten und wie Sie Volumes zwischen Containern teilen.

Anforderungen

  • Docker installiert und läuft.
  • Grundlegende Kenntnisse der Docker-Funktionalität und -Befehle

Das Docker-Dateisystem

Um Docker-Volumes zu verstehen, ist es wichtig, zuerst zu verstehen, wie das Docker-Dateisystem funktioniert.

Ein Docker-Image besteht aus mehreren schreibgeschützten Schichten. Wird ein Image aus einem Container gestartet, fügt Docker eine neue beschreibbare Schicht an der Spitze des Systems hinzu. Das wird in Docker Union File System genannt.

Jedes Mal, wenn eine Datei geändert wird, erstellt Docker eine Kopie der Datei von den schreibgeschützten Schichten  bis in die oberste beschreibbare Schicht. Dadurch bleibt die ursprüngliche (schreibgeschützte) Datei unverändert.

Wird ein Container gelöscht, geht die oberste beschreibbare Schicht verloren. Das bedeutet, dass alle Änderungen, die nach dem Start des Containers vorgenommen wurden, nicht mehr vorhanden sind.

Abhilfe durch Volumes

Ein Volume ermöglicht es, dass Daten erhalten bleiben, auch wenn ein Container gelöscht wird. Volumes sind auch eine praktische Möglichkeit, Daten zwischen dem Host und dem Container auszutauschen.

Das Einbinden des Volumes ist eine gute Lösung, um Folgendes auszuführen:

  •  Daten in einen Container übertragen
  •  Daten aus einem Container speichern
  •  Daten zwischen Containern austauschen

Docker-Volumes existieren außerhalb des Union File Systems mit seinen Read-Only und seiner beschreibbaren Schicht. Das Volume ist ein Ordner, der zwischen dem Container und dem Hostcomputer geteilt wird. Volumes können auch zwischen Containern geteilt werden.

Grundlagen der Docker-Volumes

Ein Docker-Volume "lebt" ausserhalb des Containers auf dem Host-Computer.

Aus dem Container heraus verhält sich das Volume wie ein Ordner, in dem Sie Daten speichern und aus dem Sie Daten abrufen können. Es handelt sich hier um einen Mount Point auf ein Verzeichnis auf dem Host.

Es gibt mehrere Möglichkeiten, Docker-Volumes zu erstellen und zu verwalten. Jede Methode hat ihre eigenen Vor- und Nachteile.

Verwendung des Befehls "volume create" von Docker

  • Vorteil: Schnell und einfach

  • Nachteil: Das Volume auf dem Host wird von Docker automatisch erstellt und kann schwer zu finden und zu verwenden sein

Ab der Version 1.9.0, die am 3.11.2015 veröffentlicht wurde, können Docker-Volumes nun mit dem Befehl docker volume erstellt und verwaltet werden.

Volume erstellen und benennen

Der Befehl docker volume create erstellt ein benanntes Volume. Der Name ermöglicht es Ihnen, Docker-Volumes einfach zu finden und den Containern zuzuordnen.

Um ein Volume zu erstellen, verwenden Sie den Befehl:

sudo docker volume create --name [volume name]

Um beispielsweise ein Volume mit dem Namen Data-Volume zu erstellen, lautet der Befehl:

sudo docker volume create --name data-volume

Volume im Container verwenden

Um einen Container zu starten, der ein Volume verwendet, das Sie mit docker volume create erstellt haben, fügen Sie dem Befehl docker run das folgende Argument hinzu:

-v [volume name]:[container directory] 

Um beispielsweise einen Container aus dem centos-Image mit dem Namen my-volume-test auszuführen und das Volume Data-Volume dem Verzeichnis /data des Containers zuzuordnen, lautet der Befehl:

sudo docker run -it --name my-volume-test -v data-volume:/data centos /bin/bash

Volumes auflisten

Um alle Docker-Volumes auf dem System aufzulisten, verwenden Sie den Befehl:

sudo docker volume ls

Dies gibt eine Liste aller Docker-Volumes zurück, die auf dem Host erstellt wurden.

Volume inspizieren

Um ein benanntes Volume zu inspizieren, verwenden Sie den Befehl:

sudo docker volume inspect [volume name]

Dies gibt Informationen über das Volume zurück, einschließlich des Mount Points, des Verzeicnisses auf dem Hostsystem, über das das Volume angesprochen werden kann.

Um zum Beispiel mehr Informationen über das Volume mit namen "Data" zu erhalten, das wir oben erstellt haben, ist der Befehl:

sudo docker volume inspect data-volume

Volume Entfernen

Um ein benanntes Volume zu entfernen, verwenden Sie den Befehl:

sudo docker volume rm [volume name]

Hinweis: Sie können ein Volume nicht entfernen, wenn es von einem vorhandenen Container verwendet wird. Bevor Sie das Volume entfernen, müssen Sie den Container mit folgenden Befehlen anhalten und löschen:

sudo docker stop [container name or ID]
sudo docker rm [container name or ID]

Um beispielsweise das Volume "Data"  zu löschen, müssen Sie zuerst den Container mit "my-volume-test" der es verwendet, stoppen und löschen:

sudo docker stop my-volume-test
sudo docker rm my-volume-test

Das Datenvolumen kann dann mit folgendem Befehl gelöscht werden:

sudo docker volume rm data-volume

Erstellen Sie ein Docker-Volume und geben Sie ein Verzeichnis auf dem Host an.

  • Vorteil: Dies Ermöglicht es Ihnen, einem Container einen bestimmten Ordner auf dem Host zuzuordnen

  • Nachteile: Im Gegensatz zu "Docker Create" kann kein benanntes Volume erstellt werden. Eine Automatisierung über ein Dockerfile ist nicht möglich.

Wenn Sie ein bestimmtes Verzeichnis auf Ihrem Host-Computer als Docker-Volume auf dem Container mounten möchten, fügen Sie das folgende Argument zu Ihrem Docker run-Befehl hinzu:

 -v [host directory]:[container directory]

Um beispielsweise einen neuen Container zu starten und den Ordner /webfiles auf dem Host dem Ordner /var/wwww/html auf dem Container zuzuordnen, lautet der Befehl:

sudo docker run -it -v /webfiles:/var/www/html centos /bin/bash

Testen Sie dies, indem Sie ein Verzeichnis erstellen, dass Sie dann als Docker-Volume verwenden, dies geht mit folgendem Befehl:

sudo mkdir /hostvolume

Fügen Sie mit dem Befehl eine kleine Testdatei zu diesem Verzeichnis hinzu:

sudo echo "Hello World" >> /hostvolume/host-hello.txt

Als nächstes starten Sie einen Container namens my-directory-test und ordnen /hostvolume auf dem Host /containervolume auf dem Container zu mit folgendem Befehl:

 sudo docker run -it --name my-directory-test -v /hostvolume:/containervolume centos /bin/bash

Sobald Sie sich in der Eingabeaufforderung des neuen Containers befinden, listen Sie die Dateien im freigegebenen Volume mit dem Befehl auf:

ls /containervolume

Sie sehen die Datei host-hello.txt, die wir auf dem Host erstellt haben.

Dies funktioniert auch in die entgegengesetzte Richtung. Dateien, die Sie in dieses Verzeichnis legen, werden auf dem Host angezeigt. Sie können dies vom Container aus testen, indem Sie dem freigegebenen Volume mit folgendem  Befehl eine weitere Datei hinzufügen:

echo "Hello from the container." >> /containervolume/container-hello.txt

Verlassen Sie den Container mit Strg-p + Strg-q und kehren Sie zur Eingabeaufforderung des Host-Computers zurück. Dort listen Sie die Dateien im freigegebenen Volume mit diesem Befehl auf:

sudo ls /hostvolume

Sie sehen die beiden Testdateien, die wir vom Host und vom Container aus erstellt haben.

Erstellen eines Docker-Volumes mit einer Dockerdatei

  • Vorteil: Ermöglicht die Automatisierung des Prozesses.
  • Nachteil: Es kann nicht wie mit Docker Volume Create ein benanntes Volume erstellt werden. Es kann kein Verzeichnis auf dem Host angegeben werden.

Verwenden Sie den folgenden Befehl in einer Dockerdatei, um ein gemeinsames Speichervolumen im Container zu erstellen:

VOLUME [volume path]

Um beispielsweise ein Volume /myvolume in dem Container zu erstellen, der aus der Dockerdatei gestartet werden soll, lautet der Befehl:

VOLUME /myvolume

Um dies zu testen, erstellen Sie zunächst eine Datei namens Dockerfile mit dem Befehl:

sudo nano Dockerfile

Fügen Sie folgenden Inhalt in die Datei ein:

# The source image to start with
FROM centos

# Create a volume
VOLUME /dockerfilevolume

Speichern und beenden Sie die Datei.

Als nächstes erstellen Sie mit folgendem  Befehl ein Image namens dockerfile-volumetest aus dieser Dockerdatei:

sudo docker build -t dockerfile-volumetest .

Danach starten Sie einen Container namens my-dockerfile-test aus diesem Image mit dem Befehl:

sudo docker run --name my-dockerfile-test -it dockerfile-volumetest /bin/bash

Sobald Sie sich in der Eingabeaufforderung des neuen Containers befinden, erstellen Sie mit diesem Befehl eine kleine Testdatei im freigegebenen Volume:

echo "Hello World" >> /dockerfilevolume/dockerfile-container-hello.txt

Verlassen Sie den Container mit Strg-p + Strg-q und kehren Sie zur Eingabeaufforderung des Host-Computers zurück.

Als nächstes suchen Sie den Mount Point. Verwenden Sie dazu den Befehl:

sudo docker inspect my-dockerfile-test

Scrollen Sie durch die Ausgabe, bis Sie einen Abschnitt mit dem Titel "Mounts" finden, der ungefähr so aussieht:

find docker mount point
  • Quelle ist das Verzeichnis auf dem Hostcomputer.
  • Ziel ist der Ordner auf dem Container.

Überprüfen Sie das Quellverzeichnis auf Ihrem Hostcomputer. In dem Beispiel ist der Befehl:

sudo ls  /var/lib/docker/volumes/30275034a424251a771c91b65ba44261a27f91e3f6af31097b5226b1f46bfe20/_data/test

Hier finden Sie die Datei dockerfile-container-hello.txt, die Sie auf dem Container erstellt haben.

Teilen von Volumes zwischen Containern

Es gibt viele Situationen, in denen es sinnvoll ist, ein Docker-Volume zwischen Containern zu teilen, und mehrere Möglichkeiten, dieses Ziel zu erreichen.

Freigeben eines Volumes auf dem Host

Wenn Sie ein Volume auf dem Hostcomputer erstellen, kann es von mehreren verschiedenen Containern gleichzeitig verwendet werden. Auf diese Weise können Sie Daten zwischen Containern und dem Host austauschen.

Für dieses Beispiel erstellen Sie ein Verzeichnis auf dem Host und verwenden dieses Verzeichnis als gemeinsames Volume zwischen zwei Containern.

Beginnen Sie, indem Sie mit folgendem Befehl ein Verzeichnis erstellen, das Sie als Docker-Volume verwenden können:

sudo mkdir /webdata

Erstellen Sie in diesem Verzeichnis mit diesem Befehl eine kleine Testdatei:

sudo echo "Hello from the host." >> /webdata/host-hello.txt

Als nächstes starten Sie einen Container mit dem Namen sql-database aus dem offiziellen PostgreSQL-Image und ordnen /webdata auf dem Host mit dem Befehl /data auf dem Container zu:

 sudo docker run -it --name sql-database -v /webdata:/data postgres /bin/bash

Sobald Sie sich in der Eingabeaufforderung des neuen Containers befinden, überprüfen Sie, ob das freigegebene Volume mit dem Befehl korrekt eingerichtet ist:

ls /data

Sie sehen die Datei host-hello.txt, die wir auf dem Host erstellt haben. Fügen Sie mit folgendem Befehl eine Datei zum freigegebenen Volume hinzu:

 echo "Hello from the sql-database container." >> /data/sql-hello.txt

Verlassen Sie den Container mit Strg-p + Strg-q und kehren Sie zur Eingabeaufforderung des Host-Computers zurück.

Starten Sie nun einen Container namens Webapp aus dem offiziellen PHP+Apache Image und ordnen Sie /webdata auf dem Host /var/www/html auf dem Container zu.

sudo docker run -it --name webapp -v /webdata:/var/www/html php:5.6-apache /bin/bash

Sobald Sie sich in der Eingabeaufforderung des neuen Containers befinden, überprüfen Sie mit folgendem Befehl, ob das freigegebene Volume korrekt eingerichtet wurde:

ls /var/www/html

Sie sehen sowohl die Datei host-hello.txt, die Sie auf dem Host erstellt haben als auch die Datei sql-hello.txt, die Sie auf dem sql-Datenbankcontainer erstellt haben.

Fügen Sie jetzt eine Datei aus dem zuletzt erstellten Container hinzu:

echo "Hello from the webapp container." >> /var/www/html/webapp-hello.txt

Verlassen Sie den Container mit Strg-p + Strg-q und kehren Sie zur Eingabeaufforderung des Host-Computers zurück. Auf dem Host können Sie sich alle drei Dateien mit folgendem Befehl anzeigen lassen:

sudo ls /webdata

Da sich die beiden Container nun ein Verzeichnis teilen, das auf dem Host "lebt", können Daten sofort zwischen allen drei Standorten übertragen werden, indem sie einfach in dieses Verzeichnis verschoben werden.

Einen Container als gemeinsames Datenvolumen einrichten

Sie können auch einen separaten Container als gemeinsames Datenvolumen einrichten.

Dazu legen Sie zunächst den Datencontainer an. Wenn Sie dann den Container erstellen, der diesen Datencontainer verwenden soll, fügen Sie dem Befehl docker run das folgende Argument hinzu:

 --volumes-from [name or ID of data container]

Hinweis: Dies funktioniert unabhängig davon, ob der Zielcontainer ausgeführt wird oder nicht. Docker-Volumes werden nie gelöscht und bleiben auch nach dem Stoppen des Containers erhalten.

Für dieses Beispiel erstellen Sie einen Datencontainer namens Data-Storage, der als Datenvolumen dient. Zusätzlich werden zwei weitere Container erstellt, die sich den Datencontainer als Speichervolumen teilen.

Starten Sie zunächst den Data-Storage Container aus dem offiziellen CentOS 7-Image:

sudo docker run -it -v /shared-data --name data-storage centos /bin/bash

Fügen Sie dann eine kleine Datei zum Ordner /shared-data hinzu:

echo "Hello from the data-storage container." >> /shared-data/data-storage-hello.txt

Verlassen Sie den Container mit Strg-p + Strg-q und kehren Sie zur Eingabeaufforderung des Host-Computers zurück.

Starten Sie nun den App-Container aus dem offiziellen Python-Image und mounten Sie den Datenspeicher-Container als Volume:

sudo docker run -it --name app --volumes-from data-storage python /bin/bash

Listen Sie die Dateien im freigegebenen Volume mit folgendem Befehl auf:

ls /shared-data 

Wie Sie sehen können, wurde der Ordner /shared-data aus dem Ordner /shared-data auf dem Datenspeicher-Container gemountet und enthält die Datei data-storage-hello.txt.

Fügen Sie jetzt eine Datei aus dem App-Container hinzu:

echo "Hello from the app container." >> /shared-data/app-hello.txt

Verlassen Sie den Container mit Strg-p + Strg-q und kehren Sie zur Eingabeaufforderung des Host-Computers zurück.

Starten Sie schließlich den Web Container aus dem offiziellen Apache-Image und mounten Sie den Datenspeicher-Container als Volume:

sudo docker run -it --name web --volumes-from data-storage httpd /bin/bash

Listen Sie die Dateien im freigegebenen Volume mit diesem Befehl auf:

ls /shared-data

Sie sehen hier die von uns auf den Speicher- und App-Containern erstellten Dateien.

Volume schreibgeschützt mounten

In diesem Artikel haben wir Volumes bisher mit Schreb-lese-Zugriff erstellt bzw. gemountet.

Wenn Sie einen Container darauf beschränken möchten, nur Lesezugriff auf ein Volume zu haben, fügen Sie einfach :ro zu dem in der -v-Anweisung angegebenen Containervolumen hinzu:

 docker run -v /directory:/path:ro

Dies kann für Sicherheitszwecke nützlich sein, oder wenn Sie sicherstellen möchten, dass die Daten in einem bestimmten Volume gegen versehentliches Überschreiben oder Löschen durch einen anderen Container geschützt sind.

Erstellen Sie zum Beispiel ein Volume auf dem Host mit dem Namen limited-access mit folgendem Befehl: 

sudo docker volume create --name limited-access

Führen Sie dann einen Container aus dem centos-Image mit dem Namen allowed-to-write aus und ordnen Sie das Volume Limited-Access als normales (read-write) Volume zu:

sudo docker run -it --name allowed-to-write -v limited-access:/data centos /bin/bash

Sobald Sie sich an der Eingabeaufforderung dieses Containers befinden, erstellen Sie eine Testdatei mit dem Befehl:

echo "Hello from the container that is allowed to write." >> /data/hello.txt

Verlassen Sie den Container mit Strg-p + Strg-q und kehren Sie zur Eingabeaufforderung des Host-Computers zurück.

Als nächstes führen Sie einen Container aus dem centos-Image mit dem Namen not-allowed-to-write aus und ordnen diesem das Volume Limited-Access als Read-only-Volume zu:

sudo docker run -it --name not-allowed-to-write -v limited-access:/data:ro centos /bin/bash

Wenn Sie versuchen, eine Testdatei auf dem freigegebenen Volume mit einem Befehl wie diesem zu erstellen:

echo "Hello from the container that is not allowed to write." >> /data/no-access.txt

Erhalten Sie einen Fehler, der erklärt, dass dieser Container keinen Schreibzugriff auf dieses Verzeichnis hat.

bash: /data/no-access.txt: Read-only file system