Verwalten von Containerdateisystemen

DockerDockerBeginner
Jetzt üben

This tutorial is from open-source community. Access the source code

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

Standardmäßig werden alle in einem Container erstellten Dateien auf einer beschreibbaren Container-Schicht gespeichert. Das bedeutet, dass:

  • Wenn der Container nicht mehr existiert, gehen die Daten verloren,
  • Die beschreibbare Schicht des Containers ist eng mit dem Hostcomputer verknüpft, und
  • Um das Dateisystem zu verwalten, benötigen Sie einen Speicherdreiber, der ein Union-Dateisystem bereitstellt, indem er den Linux-Kernel verwendet. Dieser zusätzliche Abstraktionsschritt reduziert die Leistung im Vergleich zu Data Volumes, die direkt auf das Dateisystem schreiben.

Docker bietet zwei Optionen, um Dateien auf dem Hostcomputer zu speichern: Volumes und Bind Mounts. Wenn Sie Docker auf Linux ausführen, können Sie auch eine tmpfs Mount verwenden, und mit Docker auf Windows können Sie auch eine benannte Pipe verwenden.

Types of Mounts
  • Volumes werden im von Docker verwalteten Hostdateisystem gespeichert.
  • Bind Mounts können an beliebiger Stelle des Hostsystems gespeichert werden.
  • tmpfs Mounts werden ausschließlich im Hostspeicher gespeichert.

Ursprünglich wurde das Flag --mount für Docker Swarm-Dienste verwendet, und das Flag --volume für einzelne Container. Ab Docker 17.06 und höher können Sie auch --mount für einzelne Container verwenden, und es ist im Allgemeinen expliziter und ausführlicher als --volume.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL docker(("Docker")) -.-> docker/ContainerOperationsGroup(["Container Operations"]) docker(("Docker")) -.-> docker/VolumeOperationsGroup(["Volume Operations"]) docker(("Docker")) -.-> docker/SystemManagementGroup(["System Management"]) docker/ContainerOperationsGroup -.-> docker/run("Run a Container") docker/ContainerOperationsGroup -.-> docker/stop("Stop Container") docker/ContainerOperationsGroup -.-> docker/rm("Remove Container") docker/ContainerOperationsGroup -.-> docker/exec("Execute Command in Container") docker/ContainerOperationsGroup -.-> docker/inspect("Inspect Container") docker/VolumeOperationsGroup -.-> docker/volume("Manage Volumes") docker/SystemManagementGroup -.-> docker/prune("Remove Unused Docker Objects") subgraph Lab Skills docker/run -.-> lab-148984{{"Verwalten von Containerdateisystemen"}} docker/stop -.-> lab-148984{{"Verwalten von Containerdateisystemen"}} docker/rm -.-> lab-148984{{"Verwalten von Containerdateisystemen"}} docker/exec -.-> lab-148984{{"Verwalten von Containerdateisystemen"}} docker/inspect -.-> lab-148984{{"Verwalten von Containerdateisystemen"}} docker/volume -.-> lab-148984{{"Verwalten von Containerdateisystemen"}} docker/prune -.-> lab-148984{{"Verwalten von Containerdateisystemen"}} end

Volumes

Ein Data Volume oder Volume ist ein Verzeichnis, das das Union File System von Docker umgeht.

Es gibt drei Arten von Volumes:

  • anonymes Volume,
  • benanntes Volume und
  • Host-Volume.

Anonymes Volume

Erstellen wir eine Instanz einer beliebten Open-Source NoSQL-Datenbank namens CouchDB und verwenden ein anonymes Volume, um die Datenfiles für die Datenbank zu speichern.

Um eine Instanz von CouchDB auszuführen, verwenden Sie das CouchDB-Image von Docker Hub unter https://hub.docker.com/_/couchdb. Die Dokumentation sagt, dass der Standard für CouchDB darin besteht, die Datenbankfiles auf dem Hostsystem auf der Festplatte mit seiner eigenen internen Volumenverwaltung zu schreiben.

Führen Sie den folgenden Befehl aus:

docker run -d -p 5984:5984 --name my-couchdb -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=passw0rd1 couchdb:3.1

CouchDB wird ein anonymes Volume erstellen und einen hashed Namen generieren. Überprüfen Sie die Volumes auf Ihrem Hostsystem:

labex:~/ $ docker volume ls
DRIVER VOLUME NAME
local 1d292aca855adb9de9be7acea88f6d3f8e6a08eef5bfd986a81f073f1906b82f

Legen Sie eine Umgebungsvariable VOLUME mit dem Wert des generierten Namens fest:

export VOLUME=<VOLUME NAME>

Und überprüfen Sie das erstellte Volume. Verwenden Sie den hashed Namen, der für das Volume generiert wurde:

$ docker volume inspect $VOLUME
[
{
  "CreatedAt": "2020-09-24T14:10:07Z",
  "Driver": "local",
  "Labels": null,
  "Mountpoint": "/var/lib/docker/volumes/f543c5319ebd96b7701dc1f2d915f21b095dfb35adbb8dc851630e098d526a50/_data",
  "Name": "f543c5319ebd96b7701dc1f2d915f21b095dfb35adbb8dc851630e098d526a50",
  "Options": null,
  "Scope": "local"
}
]

Sie sehen, dass Docker ein Volume im Docker-Hostdateisystem unter /var/lib/docker/volumes/$VOLUME_NAME/_data erstellt und verwaltet. Beachten Sie, dass dies kein Pfad auf dem Hostcomputer ist, sondern ein Teil des von Docker verwalteten Dateisystems.

Erstellen Sie eine neue Datenbank mydb und fügen Sie ein neues Dokument mit einer hello world-Nachricht hinzu.

curl -X PUT -u admin:passw0rd1 http://127.0.0.1:5984/mydb
curl -X PUT -u admin:passw0rd1 http://127.0.0.1:5984/mydb/1 -d '{"msg": "hello world"}'

Stoppen Sie den Container und starten Sie ihn erneut:

docker stop my-couchdb
docker start my-couchdb

Rufen Sie das Dokument in der Datenbank ab, um zu testen, ob die Daten persistent sind.

curl -X GET -u admin:passw0rd1 http://127.0.0.1:5984/mydb/_all_docs
curl -X GET -u admin:passw0rd1 http://127.0.0.1:5984/mydb/1

Ausgabe:

## $ curl -X GET -u admin:passw0rd1 http://127.0.0.1:5984/mydb/_all_docs
{"total_rows":1,"offset":0,"rows":[
{"id":"1","key":"1","value":{"rev":"1-c09289617e06b96bc747fb1201fea7f1"}}
]}

## $ curl -X GET -u admin:passw0rd1 http://127.0.0.1:5984/mydb/1
{"_id":"1","_rev":"1-c09289617e06b96bc747fb1201fea7f1","msg":"hello world"}

Teilen von Volumes

Sie können ein anonymes Volume mit einem anderen Container teilen, indem Sie die Option --volumes-from verwenden.

Erstellen Sie einen busybox-Container mit einem anonymen Volume, das an ein Verzeichnis /data im Container gemounted ist, und verwenden Sie Shell-Befehle, um eine Nachricht in eine Log-Datei zu schreiben.

$ docker run -it --name busybox1 -v /data busybox sh
/ ## echo "hello from busybox1" > /data/hi.log
/ ## ls /data
hi.log
/ ## exit

Stellen Sie sicher, dass der Container busybox1 gestoppt, aber nicht entfernt ist.

labex:~/ $ docker ps -a | grep busybox1
f4dbf9ee7513   busybox                               "sh"                     2 minutes ago   Exited (0) About a minute ago                                                                                                                                          busybox1

Erstellen Sie dann einen zweiten busybox-Container namens busybox2, indem Sie die Option --volumes-from verwenden, um das von busybox1 erstellte Volume zu teilen:

$ docker run --rm -it --name busybox2 --volumes-from busybox1 busybox sh
/ ## ls -al /data
total 12
drwxr-xr-x 2 root root 4096 Jan 23 07:20.
drwxr-xr-x 1 root root 4096 Jan 23 07:24..
-rw-r--r-- 1 root root 20 Jan 23 07:20 hi.log
/ ## cat /data/hi.log
hello from busybox1
/ ## exit

Docker erstellte das anonyme Volume, das Sie mithilfe der Option --volumes-from teilen konnten, und erstellte ein neues anonymes Volume.

labex:~/ $ docker volume ls
DRIVER VOLUME NAME
local 0f971b2477d5fc0d0c2b31fc908ee59d6b577b4887e381964650ce6853890dc9
local 1d292aca855adb9de9be7acea88f6d3f8e6a08eef5bfd986a81f073f1906b82f

Bereinigen Sie die vorhandenen Volumes und Container.

docker stop my-couchdb
docker rm my-couchdb
docker rm busybox1
docker volume rm $(docker volume ls -q)
docker system prune -a
clear

Benanntes Volume

Ein benanntes Volume und ein anonymes Volume sind ähnlich darin, dass Docker bestimmt, wo sie sich befinden. Ein benanntes Volume kann jedoch beim Mounten an ein Containerverzeichnis per Namen referenziert werden. Dies ist hilfreich, wenn Sie ein Volume über mehrere Container hinweg teilen möchten.

Erstellen Sie zunächst ein benanntes Volume:

docker volume create my-couchdb-data-volume

Vergewissern Sie sich, dass das Volume erstellt wurde:

$ docker volume ls
DRIVER VOLUME NAME
local my-couchdb-data-volume

Erstellen Sie nun den CouchDB-Container namens my-couchdb-name-vol, indem Sie das benannte Volume verwenden:

docker run -d -p 59840:5984 --name my-couchdb-name-vol -v my-couchdb-data-volume:/opt/couchdb/data -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=passw0rd1 couchdb:3.1

Warten Sie, bis der CouchDB-Container läuft und die Instanz verfügbar ist.

Erstellen Sie eine neue Datenbank mydb und fügen Sie ein neues Dokument mit einer hello world-Nachricht hinzu.

curl -X PUT -u admin:passw0rd1 http://127.0.0.1:59840/mydb
curl -X PUT -u admin:passw0rd1 http://127.0.0.1:59840/mydb/1 -d '{"msg": "hello world"}'

Es ist jetzt einfach, das Volume mit einem anderen Container zu teilen. Lesen Sie beispielsweise den Inhalt des Volumes mithilfe des busybox-Images und teilen Sie das my-couchdb-data-volume-Volume, indem Sie das Volume an ein Verzeichnis im busybox-Container mounten.

labex:~/ $ docker run --rm -it --name busybox -v my-couchdb-data-volume:/myvolume busybox sh
/ #
/ ## ls -al /myvolume
total 40
drwxr-xr-x 4 5984 5984 4096 Jan 23 07:30.
drwxr-xr-x 1 root root 4096 Jan 23 07:31..
drwxr-xr-x 2 5984 5984 4096 Jan 23 07:29.delete
-rw-r--r-- 1 5984 5984 8388 Jan 23 07:30 _dbs.couch
-rw-r--r-- 1 5984 5984 8385 Jan 23 07:29 _nodes.couch
drwxr-xr-x 4 5984 5984 4096 Jan 23 07:30 shards
/ ## exit

Sie können das von Docker verwaltete Dateisystem für Volumes überprüfen, indem Sie einen busybox-Container mit privilegierten Rechten ausführen und die Prozess-ID auf host setzen, um das Hostsystem zu überprüfen, und zum Docker verwalteten Verzeichnissen navigieren.

docker run -it --privileged --pid=host busybox nsenter -t 1 -m -u -n -i sh
/ ## ls -l /var/lib/docker/volumes
total 28
-rw------- 1 root root 32768 Nov 10 15:54 metadata.db
drwxr-xr-x 3 root root 4096 Nov 10 15:54 my-couchdb-data-volume
/ ## exit

Bereinigen:

docker stop my-couchdb
docker rm my-couchdb
docker volume rm my-couchdb-data-volume
docker system prune -a
docker volume prune
clear

Host-Volume

Wenn Sie das Volumedirectory direkt von der Hostmaschine aus einfach zugreifen möchten, anstatt die von Docker verwalteten Verzeichnisse zu verwenden, können Sie ein Host-Volume erstellen.

Verwenden Sie ein Verzeichnis im aktuellen Arbeitsverzeichnis (angegeben mit dem Befehl pwd), das data heißt, oder wählen Sie Ihr eigenes Datenverzeichnis auf der Hostmaschine, z.B. /home/couchdb/data. Wir lassen Docker das Verzeichnis $(pwd)/data erstellen, wenn es noch nicht existiert. Wir mounten das Host-Volume innerhalb des CouchDB-Containers an das Containerverzeichnis /opt/couchdb/data, das das Standarddatenverzeichnis für CouchDB ist.

Führen Sie den folgenden Befehl aus:

cd /home/labex/project
docker run -d -p 5984:5984 --name my-couchdb -v $(pwd)/data:/opt/couchdb/data -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=passw0rd1 couchdb:3.1

Vergewissern Sie sich, dass ein Verzeichnis data erstellt wurde:

$ ls -al
total 20
drwxrwxr-x 3 labex labex 4096 Aug 29 14:14.
drwxr-x--- 25 labex labex 4096 Aug 29 14:14..
drwxr-xr-x 3 5984 5984 4096 Aug 29 14:14 data

und dass CouchDB hier Datenfiles erstellt hat:

$ ls -al data
total 32
drwxr-xr-x 3 5984 5984 4096 Aug 29 14:14.
drwxrwxr-x 3 labex labex 4096 Aug 29 14:14..
-rw-r--r-- 1 5984 5984 4257 Aug 29 14:14 _dbs.couch
drwxr-xr-x 2 5984 5984 4096 Aug 29 14:14.delete
-rw-r--r-- 1 5984 5984 8385 Aug 29 14:14 _nodes.couch

Überprüfen Sie auch, dass jetzt kein verwaltetes Volume von Docker erstellt wurde, da wir jetzt ein Host-Volume verwenden.

docker volume ls

und

docker run -it --privileged --pid=host busybox nsenter -t 1 -m -u -n -i sh
sh-5.1## ls -l /var/lib/docker/volumes
total 28
brw------- 1 root root 252, 3 Jan 23 15:15 backingFsBlockDev
-rw------- 1 root root 32768 Jan 23 15:33 metadata.db
drwx-----x 3 root root 4096 Jan 23 15:26 my-couchdb-data-volume
sh-5.1## exit

Erstellen Sie eine neue Datenbank mydb und fügen Sie ein neues Dokument mit einer hello world-Nachricht hinzu.

curl -X PUT -u admin:passw0rd1 http://127.0.0.1:5984/mydb
curl -X PUT -u admin:passw0rd1 http://127.0.0.1:5984/mydb/1 -d '{"msg": "hello world"}'

Beachten Sie, dass CouchDB einen Ordner shards erstellt hat:

$ ls -al data
total 40
drwxr-xr-x 4 5984 5984 4096 Aug 29 14:15.
drwxrwxr-x 3 labex labex 4096 Aug 29 14:14..
-rw-r--r-- 1 5984 5984 8388 Aug 29 14:15 _dbs.couch
drwxr-xr-x 2 5984 5984 4096 Aug 29 14:14.delete
-rw-r--r-- 1 5984 5984 8385 Aug 29 14:14 _nodes.couch
drwxr-xr-x 4 5984 5984 4096 Aug 29 14:15 shards

Listen Sie den Inhalt des Ordners shards auf:

$ ls -al data/shards
total 16
drwxr-xr-x 4 5984 5984 4096 Aug 29 14:15.
drwxr-xr-x 4 5984 5984 4096 Aug 29 14:15..
drwxr-xr-x 2 5984 5984 4096 Aug 29 14:15 00000000-7fffffff
drwxr-xr-x 2 5984 5984 4096 Aug 29 14:15 80000000-ffffffff

und das erste Shard:

$ ls -al data/shards/00000000-7fffffff/
total 20
drwxr-xr-x 2 5984 5984 4096 Aug 29 14:15.
drwxr-xr-x 4 5984 5984 4096 Aug 29 14:15..
-rw-r--r-- 1 5984 5984 8346 Aug 29 14:15 mydb.1693289721.couch

Ein Shard ist eine horizontale Partition von Daten in einer Datenbank. Die Aufteilung von Daten in Shards und die Verteilung von Kopien jedes Shards auf verschiedene Knoten in einem Cluster gewährleistet eine höhere Zuverlässigkeit der Daten bei einem Knotenausfall. CouchDB shardet Datenbanken automatisch und verteilt die Teilmengen von Dokumenten zwischen den Knoten.

Bereinigen:

docker stop my-couchdb
docker rm my-couchdb
sudo rm -rf $(pwd)/data
docker system prune -a

Bind Mounts

Docker empfiehlt die mount-Syntax gegenüber der volume-Syntax. Bind Mounts haben im Vergleich zu Volumes eingeschränkte Funktionen. Eine Datei oder ein Verzeichnis wird beim Mounten in einen Container anhand seines vollständigen Pfads auf der Hostmaschine referenziert. Bind Mounts setzen voraus, dass das Dateisystem der Hostmaschine eine bestimmte Verzeichnisstruktur zur Verfügung hat, und Sie können die Docker-Befehlszeilenschnittstelle (CLI) nicht verwenden, um Bind Mounts zu verwalten. Beachten Sie, dass Bind Mounts das Hostdateisystem über Prozesse, die in einem Container laufen, verändern können.

Anstatt die -v-Syntax mit drei durch Doppelpunkte getrennten Feldern zu verwenden, ist die mount-Syntax ausführlicher und verwendet mehrere Schlüssel-Wert-Paare:

  • type: bind, volume oder tmpfs,
  • source: Pfad zur Datei oder zum Verzeichnis auf der Hostmaschine,
  • destination: Pfad im Container,
  • readonly,
  • bind-propagation: rprivate, private, rshared, shared, rslave, slave,
  • consistency: consistent, delegated, cached,
  • mount.
cd /home/labex/project
mkdir data
docker run -it --name busybox --mount type=bind,source="$(pwd)"/data,target=/data busybox sh

Geben Sie den Befehl im Container ein:

echo "hello busybox" > /data/hi.txt
exit

Überprüfen Sie, ob die Datei auf der Hostmaschine erstellt wurde.

cat data/hi.txt

[Optional] OverlayFS

OverlayFS ist eine Implementierung eines Union Mount Dateisystems für Linux. Um zu verstehen, was ein Docker-Volume ist, hilft es, zu verstehen, wie Layer und das Dateisystem in Docker funktionieren.

Um einen Container zu starten, nimmt Docker das schreibgeschützte Image und erstellt eine neue schreibende Schicht darüber. Um die Layer als eine Einheit zu betrachten, verwendet Docker ein Union File System oder OverlayFS (Overlay File System), speziell den Speicherdreiber overlay2.

Um die von Docker auf dem Host verwalteten Dateien zu sehen, müssen Sie Zugang zum Docker-Prozessdateisystem haben. Mit den Flags --privileged und --pid=host können Sie vom Inneren eines Containers wie busybox aus auf den Prozess-ID-Namespace des Hosts zugreifen. Anschließend können Sie zu dem Verzeichnis /var/lib/docker/overlay2 von Docker navigieren, um die heruntergeladenen Layer zu sehen, die von Docker verwaltet werden.

Um die aktuelle Liste der Layer in Docker anzuzeigen:

$ docker run -it --privileged --pid=host busybox nsenter -t 1 -m -u -n -i sh

/ ## ls -l /var/lib/docker/overlay2
total 16
drwx------ 3 root root 4096 Sep 25 19:44 0e55ecaa4d17c353191e68022d9a17fde64fb5e9217b07b5c56eb4c74dad5b32
drwx------ 5 root root 4096 Sep 25 19:44 187854d05ccd18980642e820b0d2be6a127ba85d8ed96315bb5ae37eb1add36d
drwx------ 4 root root 4096 Sep 25 19:44 187854d05ccd18980642e820b0d2be6a127ba85d8ed96315bb5ae37eb1add36d-init
drwx------ 2 root root 4096 Sep 25 19:44 l

/ ## exit

Ziehen Sie das ubuntu-Image herunter und überprüfen Sie es erneut:

docker pull ubuntu
docker run -it --privileged --pid=host busybox nsenter -t 1 -m -u -n -i sh

Geben Sie den Befehl ein, um die Liste der Layer erneut anzuzeigen:

ls -l /var/lib/docker/overlay2/ & exit

Sie sehen, dass beim Herunterladen des ubuntu-Images implizit 4 neue Layer heruntergeladen wurden:

  • a611792b4cac502995fa88a888261dfba0b5d852e72f9db9e075050991423779
  • d181f1a41fc35a45c16e8bfcb8eee6f768f3b98f82210a43ea65f284a45fcd65
  • dac2f37f6280a076836d39b87b0ae5ebf5c0d386b6d8b991b103aadbcebaa7c6
  • f3e921b440c37c86d06cd9c9fb70df50edad553c36cc87f84d5eeba734aae709

Der Speicherdreiber overlay2 legt im Wesentlichen verschiedene Verzeichnisse auf dem Host übereinander und stellt sie als ein einzelnes Verzeichnis dar.

  • Basisschicht oder lowerdir,
  • diff-Schicht oder upperdir,
  • Overlay-Schicht (Benutzeransicht) und
  • work-Verzeichnis.

OverlayFS bezieht sich auf die unteren Verzeichnisse als lowerdir, das die Basisimage und die schreibgeschützten (R/O) Layer enthält, die heruntergeladen werden.

Das obere Verzeichnis wird upperdir genannt und ist die schreibende (R/W) Container-Schicht.

Die vereinigte Ansicht oder die overlay-Schicht wird merged genannt.

Schließlich ist ein workdir erforderlich, das ein leeres Verzeichnis ist, das von overlay für interne Zwecke verwendet wird.

Der overlay2-Treiber unterstützt bis zu 128 untere OverlayFS-Layer. Das l-Verzeichnis enthält verkürzte Layer-Identifikatoren als symbolische Links.

Overlay2 Storage Driver

Bereinigen:

docker system prune -a
clear

Zusammenfassung

In diesem Lab haben Sie gelernt, wie Sie Daten in Containern mit Volumes und Bind Mounts verwalten. Sie haben auch über den Speicherdreiber overlay2 und dessen Verwendung des Union File Systems zur Verwaltung von Schichten erfahren.