So geben Sie Daten zwischen Docker-Containern frei

Einführung

Docker ist ein beliebtes Containerisierungstool, mit dem Softwareanwendungen ein Dateisystem erhalten, das alles enthält, was sie zum Ausführen benötigen. Durch die Verwendung von Docker-Containern wird sichergestellt, dass sich die Software unabhängig von ihrem Bereitstellungsort gleich verhält, da ihre Laufzeitumgebung konsistent ist.

Im Allgemeinen sind Docker-Container kurzlebig und werden nur so lange ausgeführt, wie der im Container ausgegebene Befehl ausgeführt wird. Manchmal müssen Anwendungen jedoch den Zugriff auf Daten freigeben oder Daten beibehalten, nachdem ein Container gelöscht wurde. Datenbanken, benutzergenerierte Inhalte für eine Website und Protokolldateien sind nur einige Beispiele für Daten, die in einem Docker-Image nicht oder nur unpraktisch enthalten sind, auf die Anwendungen jedoch zugreifen müssen. Der permanente Zugriff auf Daten wird über Docker Volumes bereitgestellt.

Docker-Volumes können mit demselben Befehl erstellt und angehängt werden, mit dem ein Container erstellt wird, oder sie können unabhängig von Containern erstellt und später angehängt werden. In diesem Artikel werden vier verschiedene Möglichkeiten für die gemeinsame Nutzung von Daten zwischen Containern beschrieben.

Voraussetzungen

Um diesem Artikel zu folgen, benötigen Sie einen Ubuntu 18.04-Server mit folgenden Eigenschaften:

Schritt 1 - Erstellen eines unabhängigen Volumes

Mit dem in Docker 1.9 eingeführten Befehl + docker volume create + können Sie ein Volume erstellen, ohne es einem bestimmten Container zuzuordnen. Mit diesem Befehl fügen wir ein Volume mit dem Namen "+ DataVolume1 +" hinzu:

docker volume create --name DataVolume1

Der Name wird angezeigt und zeigt an, dass der Befehl erfolgreich war:

OutputDataVolume1

Um das Volume zu nutzen, erstellen wir einen neuen Container aus dem Ubuntu-Image und verwenden das Flag "+ - rm ", um es beim Beenden automatisch zu löschen. Wir werden auch " -v " verwenden, um das neue Volume bereitzustellen. ` -v +` erfordert den Namen des Volumes, einen Doppelpunkt und den absoluten Pfad zu der Stelle, an der das Volume im Container erscheinen soll. Wenn die Verzeichnisse im Pfad nicht als Teil des Images vorhanden sind, werden sie bei Ausführung des Befehls erstellt. Wenn sie do vorhanden sind, wird der vorhandene Inhalt auf dem bereitgestellten Volume ausgeblendet:

docker run -ti --rm -v DataVolume1:/datavolume1 ubuntu

Schreiben Sie im Container einige Daten auf das Volume:

echo "Example1" > /datavolume1/Example1.txt

Da wir das Flag "+ - rm +" verwendet haben, wird unser Container beim Verlassen automatisch gelöscht. Unser Band wird jedoch weiterhin zugänglich sein.

exit

Wir können überprüfen, ob das Volume auf unserem System vorhanden ist mit + docker volume inspect +:

docker volume inspect DataVolume1
Output[
   {
       "CreatedAt": "2018-07-11T16:57:54Z",
       "Driver": "local",
       "Labels": {},
       "Mountpoint": "/var/lib/docker/volumes/DataVolume1/_data",
       "Name": "DataVolume1",
       "Options": {},
       "Scope": "local"
   }
]

Beginnen wir als nächstes einen neuen Container und fügen "+ DataVolume1 +" hinzu:

docker run --rm -ti -v DataVolume1:/datavolume1 ubuntu

Überprüfen Sie den Inhalt:

cat /datavolume1/Example1.txt
OutputExample1

Verlasse den Container:

exit

In diesem Beispiel haben wir ein Volume erstellt, es an einen Container angehängt und dessen Persistenz überprüft.

Schritt 2 - Erstellen eines Volumes, das beim Entfernen des Containers erhalten bleibt

In unserem nächsten Beispiel erstellen wir ein Volume zur gleichen Zeit wie der Container, löschen den Container und hängen das Volume an einen neuen Container an.

Wir werden den Befehl + docker run + verwenden, um einen neuen Container mit dem Ubuntu-Basis-Image zu erstellen. + -t + gibt uns ein Terminal und + -i + erlaubt uns, mit ihm zu interagieren. Der Übersichtlichkeit halber verwenden wir "+ - name +", um den Container zu identifizieren.

Mit dem Flag "+ -v " können wir ein neues Volume erstellen, das wir " DataVolume2 " nennen. Wir verwenden einen Doppelpunkt, um diesen Namen vom Pfad zu trennen, in dem das Volume im Container bereitgestellt werden soll. Schließlich geben wir das Basis-Ubuntu-Image an und verwenden den Standardbefehl in der Docker-Datei des https://github.com/dockerfile/ubuntu/blob/master/Dockerfile#L32[Ubuntu-Basis-Images], ` bash +`, bis Lass uns in eine Shell fallen:

docker run -ti --name=Container2 -v DataVolume2:/datavolume2 ubuntu

Im Container werden einige Daten auf das Volume geschrieben:

echo "Example2" > /datavolume2/Example2.txt
cat /datavolume2/Example2.txt
OutputExample2

Verlassen wir den Container:

exit

Wenn wir den Container neu starten, wird das Volume automatisch bereitgestellt:

docker start -ai Container2

Vergewissern wir uns, dass das Volume tatsächlich aktiviert wurde und unsere Daten noch vorhanden sind:

cat /datavolume2/Example2.txt
OutputExample2

Zum Schluss beenden wir und räumen auf:

exit

Docker lässt uns ein Volume nicht entfernen, wenn es von einem Container referenziert wird. Mal sehen, was passiert, wenn wir versuchen:

docker volume rm DataVolume2

Die Nachricht teilt uns mit, dass das Volume noch verwendet wird, und liefert die Langversion der Container-ID:

OutputError response from daemon: unable to remove volume: remove DataVolume2: volume is in use - []

Mit dieser ID können wir den Container entfernen:

docker rm
Outputd0d2233b668eddad4986313c7a4a1bc0d2edaf0c7e1c02a6a6256de27db17a63

Das Entfernen des Containers hat keinen Einfluss auf das Volumen. Wir können sehen, dass es immer noch auf dem System vorhanden ist, indem wir die Volumes mit + docker volume ls + auflisten:

docker volume ls
OutputDRIVER              VOLUME NAME
local               DataVolume2

Und wir können + docker volume rm + verwenden, um es zu entfernen:

docker volume rm DataVolume2

In diesem Beispiel haben wir gleichzeitig mit dem Erstellen eines Containers ein leeres Datenvolumen erstellt. In unserem nächsten Beispiel werden wir untersuchen, was passiert, wenn wir ein Volume mit einem Containerverzeichnis erstellen, das bereits Daten enthält.

Schritt 3 - Erstellen eines Volumes aus einem vorhandenen Verzeichnis mit Daten

Im Allgemeinen ist das unabhängige Erstellen eines Volumes mit "+ docker volume create +" und das Erstellen eines Volumes beim Erstellen eines Containers mit einer Ausnahme äquivalent. Wenn wir ein Volume gleichzeitig mit dem Erstellen eines Containers erstellen und den Pfad zu einem Verzeichnis angeben, das Daten im Basisimage enthält, werden diese Daten in das Volume kopiert.

Als Beispiel erstellen wir einen Container und fügen das Datenvolumen unter "+ / var +" hinzu, einem Verzeichnis, das Daten im Basis-Image enthält:

docker run -ti --rm -v DataVolume3:/var ubuntu

Der gesamte Inhalt aus dem Basis-Image-Verzeichnis "+ / var" wird in das Volume kopiert, und wir können dieses Volume in einem neuen Container bereitstellen.

Verlasse den aktuellen Container:

exit

Dieses Mal verwenden wir nicht den Standardbefehl "+ bash " des Basis-Images, sondern geben unseren eigenen Befehl " ls +" aus, der den Inhalt des Volumes anzeigt, ohne die Shell aufzurufen:

docker run --rm -v DataVolume3:/datavolume3 ubuntu ls datavolume3

Das Verzeichnis "+ datavolume3 " enthält jetzt eine Kopie des Inhalts des " / var +" - Verzeichnisses des Basisimages:

Outputbackups
cache
lib
local
lock
log
mail
opt
run
spool
tmp

Es ist unwahrscheinlich, dass wir "+ / var / +" auf diese Weise mounten möchten. Dies kann jedoch hilfreich sein, wenn wir ein eigenes Image erstellt haben und auf einfache Weise Daten aufbewahren möchten. In unserem nächsten Beispiel zeigen wir, wie ein Volume von mehreren Containern gemeinsam genutzt werden kann.

Schritt 4 - Daten zwischen mehreren Docker-Containern austauschen

Bisher haben wir jeweils ein Volume an einen Container angehängt. Häufig möchten wir, dass mehrere Container an dasselbe Datenvolumen angehängt werden. Dies ist relativ einfach zu bewerkstelligen, aber es gibt eine wichtige Einschränkung: Derzeit behandelt Docker die Dateisperrung nicht. Wenn Sie mehrere Container benötigen, die auf das Volume schreiben, müssen die Anwendungen, die in diesen Containern ausgeführt werden, so konzipiert sein, dass sie in gemeinsam genutzte Datenspeicher schreiben, um eine Beschädigung der Daten zu verhindern.

Erstellen Sie Container4 und DataVolume4

Verwenden Sie "+ docker run ", um einen neuen Container mit dem Namen " Container4 +" und einem angehängten Datenvolumen zu erstellen:

docker run -ti --name=Container4 -v DataVolume4:/datavolume4 ubuntu

Als Nächstes erstellen wir eine Datei und fügen Text hinzu:

echo "This file is shared between containers" > /datavolume4/Example4.txt

Dann verlassen wir den Container:

exit

Dadurch kehren wir zur Host-Eingabeaufforderung zurück, in der wir einen neuen Container erstellen, der das Datenvolumen von "+ Container4 +" bereitstellt.

Erstellen Sie Container5 und hängen Sie Volumes von Container4 ein

Wir werden + Container5 + erstellen und die Volumes von + Container4 + mounten:

docker run -ti --name=Container5 --volumes-from Container4 ubuntu

Überprüfen wir die Datenpersistenz:

cat /datavolume4/Example4.txt
OutputThis file is shared between containers

Hängen wir nun einen Text aus "+ Container5 +" an:

echo "Both containers can write to DataVolume4" >> /datavolume4/Example4.txt

Zum Schluss verlassen wir den Container:

exit

Als nächstes prüfen wir, ob Ihre Daten in "+ Container 4" noch vorhanden sind.

In Container5 vorgenommene Änderungen anzeigen

Lassen Sie uns nach den Änderungen suchen, die von "+ Container5 " in das Datenvolumen geschrieben wurden, indem Sie " Container4 +" neu starten:

docker start -ai Container4

Überprüfen Sie die Änderungen:

cat /datavolume4/Example4.txt
OutputThis file is shared between containers
Both containers can write to DataVolume4

Nachdem wir überprüft haben, dass beide Container vom Datenvolumen lesen und schreiben konnten, verlassen wir den Container:

exit

Auch hier verarbeitet Docker keine Dateisperrung, daher müssen Anwendungen die Dateisperrung selbst berücksichtigen. Es ist möglich, ein Docker-Volume schreibgeschützt bereitzustellen, um sicherzustellen, dass keine Datenbeschädigung versehentlich auftritt, wenn ein Container schreibgeschützten Zugriff benötigt, indem Sie "+: ro +" hinzufügen. Schauen wir uns an, wie das funktioniert.

Starten Sie Container 6 und stellen Sie das Volume schreibgeschützt bereit

Nachdem ein Volume in einem Container bereitgestellt wurde, können Sie statt wie bei einem typischen Linux-Dateisystem einen neuen Container erstellen, der wie gewünscht bereitgestellt wird, und bei Bedarf den vorherigen Container entfernen. Um das Volume schreibgeschützt zu machen, fügen wir "+: ro +" an das Ende des Containernamens an:

docker run -ti --name=Container6 --volumes-from Container4:ro ubuntu

Wir überprüfen den schreibgeschützten Status, indem wir versuchen, unsere Beispieldatei zu entfernen:

rm /datavolume4/Example4.txt
Outputrm: cannot remove '/datavolume4/Example4.txt': Read-only file system

Schließlich verlassen wir den Container und bereinigen unsere Testcontainer und -volumina:

exit

Nun, da wir fertig sind, bereinigen wir unsere Container und unser Volumen:

docker rm Container4 Container5 Container6
docker volume rm DataVolume4

In diesem Beispiel wird gezeigt, wie Daten mithilfe eines Datenvolumes zwischen zwei Containern geteilt werden und wie ein Datenvolumen als schreibgeschützt bereitgestellt wird.

Fazit

In diesem Lernprogramm haben wir ein Datenvolumen erstellt, mit dem Daten auch nach dem Löschen eines Containers beibehalten werden können. Wir haben Datenvolumen zwischen Containern geteilt, mit dem Vorbehalt, dass Anwendungen für die Dateisperrung entwickelt werden müssen, um eine Beschädigung der Daten zu verhindern. Abschließend wurde gezeigt, wie ein freigegebenes Volume im schreibgeschützten Modus bereitgestellt wird. Wenn Sie mehr über den Datenaustausch zwischen Containern und dem Hostsystem erfahren möchten, lesen Sie https://www.digitalocean.com/community/tutorials/how-to-share-data-between-the-docker-container-and- the-host [So geben Sie Daten zwischen dem Docker-Container und dem Host frei].