Docker-Volumes vs. Bind Mounts: Containerdaten richtig aufbewahren
Entfernen Sie einen Container und seine Daten gehen mit ihm, es sei denn, Sie bewahren ihn an einem sichereren Ort auf. Erfahren Sie den Unterschied zwischen Volumes, Bind-Mounts und tmpfs, wann Sie die einzelnen Volumes verwenden und wie Sie das Wesentliche sichern.
- Die beschreibbare Ebene eines Containers wird zusammen mit dem Container gelöscht, daher müssen wichtige Daten bereitgestellt werden.
- Benannte Volumes werden von Docker verwaltet und sind die übliche Wahl für Datenbanken und Produktionsdaten.
- Bind-Mounts ordnen einen Host-Ordner zu, was sie ideal für Live-Code während der Entwicklung macht.
docker compose down -vlöscht Volumes. Gehen Sie daher vorsichtig damit um und bewahren Sie getestete Backups auf.
Sie starten eine Datenbank in einem Container, fügen einige Daten hinzu, entfernen den Container und starten einen neuen. Die Daten sind weg. Fast jeder lernt diese Lektion auf die harte Tour. Docker-Volumes und Bind-Mounts dienen dazu, Daten über die Lebensdauer eines Containers hinaus am Leben zu halten.
In diesem Leitfaden wird erklärt, wie die einzelnen Funktionen funktionieren und wie man sie auswählt. Die Befehle und Dateien hier sind Standardbeispiele, die auf dem dokumentierten Verhalten von Docker basieren, und wir haben sie für diesen Artikel nicht ausgeführt, also probieren Sie sie zuerst mit Wegwerfdaten aus. Details können zwischen Docker-Versionen und auf Docker Desktop unterschiedlich sein. Wenn Sie neu im Umgang mit Containern sind, beginnen Sie mit unserem Docker-Tutorial für Anfänger.
Warum Containerdaten verschwinden
Ein Docker-Image besteht aus schreibgeschützten Ebenen. Wenn ein Container gestartet wird, fügt Docker oben eine dünne beschreibbare Ebene hinzu und alle Änderungen werden dort gespeichert. Diese Ebene übersteht einen Stopp und Neustart, wird jedoch entfernt, wenn der Container gelöscht wird.
docker run -d --name db -e POSTGRES_PASSWORD=devonly postgres:17
# ... create tables and add data ...
docker rm -f db
docker run -d --name db -e POSTGRES_PASSWORD=devonly postgres:17
# The data you added is not there
Dies ist beabsichtigt, da Sie so Behälter frei austauschen können. Das bedeutet allerdings, dass alles, was Sie aufbewahren müssen, außerhalb des Behälters aufbewahrt werden muss. Dafür gibt es drei Möglichkeiten:
| Typ | Gespeichert in | Überlebt die Containerentfernung? |
|---|---|---|
| Benannter Datenträger | Ein von Docker verwalteter Bereich | Ja |
| Halterung binden | Ein von Ihnen gewählter Hostpfad | Ja |
| tmpfs-Mount | Host-Speicher | Nein |
Docker-Volumes vs. Bind-Mounts nebeneinander
| Aspekt | Benannter Datenträger | Halterung binden |
|---|---|---|
| Verwaltet von | Docker | Du |
| Standort | Dockers Lagerbereich | Beliebiger Pfad auf dem Host |
| Hängt von den Hostordnern ab? | Nein | Ja |
| Bearbeitung vom Host aus | Vom Design her umständlich | Ganz einfach, Änderungen werden sofort angezeigt |
| Leeres Ziel aus Bild vorab ausgefüllt? | Ja | Nein, der Hostpfad verbirgt es |
| Docker-CLI-Befehle | Ja, docker volume |
Nein |
| Treiber für Remote-Speicher | Ja | Nein |
| Am besten für | Datenbanken, Produktionsdaten | Quellcode in Entwicklung |
Benannte Bände
Ein Volume ist ein von Docker erstellter und verwalteter Speicher. Sie nennen es namentlich und müssen sich nicht darum kümmern, wo es physisch lebt.
docker volume create pgdata
docker run -d --name db \
-e POSTGRES_PASSWORD=devonly \
-v pgdata:/var/lib/postgresql/data \
postgres:17
Jetzt befinden sich die Datenbankdateien in pgdata. Löschen Sie den Container und starten Sie einen neuen mit demselben Volumen. Ihre Daten sind dann weiterhin vorhanden. Unter Linux liegen Volumes normalerweise unter /var/lib/docker/volumes/, Sie sollten diese Dateien jedoch nicht direkt bearbeiten. Auf Docker Desktop befinden sie sich in einer virtuellen Maschine, nicht in einem normalen Ordner.
Der Pfad innerhalb des Containers hängt vom Bild ab. Überprüfen Sie daher die Dokumentation des Bildes. Das Mounten auf den falschen Pfad ist ein klassischer Fehler: Alles scheint zu funktionieren, aber die Daten werden immer noch in die Containerschicht geschrieben. Auch neuere Hauptversionen eines Images können diesen Pfad ändern. Lesen Sie daher vor dem Upgrade die Versionshinweise.
Docker erstellt automatisch ein benanntes Volume, wenn es nicht existiert. Ein anonymes Volume, das ohne Namen erstellt wird, funktioniert ebenfalls, erhält aber eine lange zufällige ID und kann leicht den Überblick verlieren. Geben Sie Ihren Bänden immer Namen.
Reittiere binden
Ein Bind-Mount ordnet einen bestimmten Hostpfad direkt dem Container zu. Beide Seiten sehen sofort die gleichen Dateien. Dies macht es perfekt für die Entwicklung, da Änderungen in Ihrem Editor im laufenden Container wirksam werden, ohne dass ein Neuaufbau erforderlich ist:
docker run -d --name web \
-p 8080:80 \
-v "$(pwd)/site:/usr/share/nginx/html:ro" \
nginx:1.27
Bearbeiten Sie eine Datei in site/, aktualisieren Sie den Browser und Sie werden die Änderung sehen. Durch :ro ist der Mount innerhalb des Containers schreibgeschützt, was eine gute Angewohnheit ist, wenn der Container dort nicht schreiben muss.
Bind-Reittiere bringen einige Kompromisse mit sich:
- Sie binden Sie an den Host. Der Pfad muss auf jedem Computer vorhanden sein, sodass Setups weniger portierbar sind.
- Sie verbergen den Inhalt des Bildes. Wenn Sie über
/appmontieren, wird alles, was sich im Bild befand, unsichtbar. Ein häufiges Beispiel ist das Verschwinden vonnode_modules. - Sie machen den Host verfügbar. Ein Container mit einem beschreibbaren Mount kann echte Hostdateien ändern oder löschen. Mounten Sie niemals sensible Pfade wie
/oder den Docker-Socket, es sei denn, Sie verstehen das Risiko vollständig. - Die Leistung kann variieren. Auf Docker Desktop für macOS und Windows überschreitet die Dateifreigabe eine Virtualisierungsgrenze und kann langsamer sein als unter Linux.
tmpfs wird bereitgestellt
Ein tmpfs-Mount befindet sich im Speicher des Hosts und wird niemals in die Containerschicht geschrieben. Es verschwindet, wenn der Container stoppt, und eignet sich daher für temporäre Dateien, Caches und kurzlebige sensible Daten:
docker run -d --tmpfs /app/cache:size=64m myapp:1.0
tmpfs ist auf Linux-Hosts verfügbar. Es kann auch Datenbanken in wegwerfbaren Testumgebungen beschleunigen, in denen Sie sich nicht um die Aufbewahrung der Daten kümmern.
-v oder –mount?
Beide Flags funktionieren. --mount ist länger, aber expliziter, und viele Leute bevorzugen es in Skripten:
# Short form
docker run -v pgdata:/var/lib/postgresql/data postgres:17
# Explicit form
docker run --mount type=volume,source=pgdata,target=/var/lib/postgresql/data postgres:17
# Bind mount, read-only
docker run --mount type=bind,source="$(pwd)"/site,target=/usr/share/nginx/html,readonly nginx:1.27
Es gibt einen bedeutsamen Unterschied. Mit -v wird ein fehlender Hostpfad als leerer Ordner für Sie erstellt, der einen Tippfehler verbergen kann. Bei --mount und einem Bind-Typ meldet Docker stattdessen einen Fehler. Auch bei -v entscheidet die linke Seite über den Typ: Ein Name bedeutet ein Volume und ein Pfad bedeutet ein Bind-Mount. -v data:/x und -v ./data:/x machen also sehr unterschiedliche Dinge.
Volumes in Docker Compose
Die meisten realen Projekte deklarieren die Speicherung in einer Compose-Datei. Hier werden beide Arten verwendet, jede für ihre jeweilige Aufgabe:
services:
web:
build: .
ports:
- "3000:3000"
volumes:
- ./src:/app/src # bind mount: live code
depends_on:
- db
db:
image: postgres:17
environment:
POSTGRES_PASSWORD: devonly
volumes:
- pgdata:/var/lib/postgresql/data # named volume: data
volumes:
pgdata:
Benannte Volumes müssen im Abschnitt volumes der obersten Ebene deklariert werden. Compose stellt dem tatsächlichen Namen den Projektnamen voran. Eine vollständige Anleitung finden Sie in unserem Docker Compose-Tutorial.
Tipp: docker compose down behält benannte Volumes, docker compose down -v löscht sie jedoch zusammen mit Ihren Daten. Seien Sie besonders vorsichtig bei Skripten und Shell-Verläufen, die -v enthalten.
Nützliche Lautstärkebefehle
| Befehl | Was es bewirkt |
|---|---|
Docker-Volume ls |
Listet Bände auf |
Docker-Volume-Erstellungsname |
Erstellt ein Volumen |
Docker-Volume-Inspect-Name |
Zeigt Details an, einschließlich des Standorts |
Docker-Volume-RM-Name |
Löscht ein Volume und seine Daten |
Docker-Volume bereinigen |
Entfernt nicht verwendete Volumes |
Docker-System df -v |
Zeigt die Festplattennutzung, einschließlich Volumes |
Überprüfen Sie, was prune entfernt, bevor Sie es bestätigen, da dies nicht rückgängig gemacht werden kann. Volumes, die derzeit kein Container nutzt, können dennoch wichtige Daten enthalten.
Ein Volume sichern und wiederherstellen
Ein Volume kann gesichert werden, indem ein kurzlebiger Container ausgeführt wird, der sowohl das Volume als auch einen Hostordner bereitstellt:
# Back up
docker run --rm \
-v pgdata:/data:ro \
-v "$(pwd)":/backup \
alpine tar czf /backup/pgdata.tar.gz -C /data .
# Restore into a new volume
docker volume create pgdata_restored
docker run --rm \
-v pgdata_restored:/data \
-v "$(pwd)":/backup \
alpine tar xzf /backup/pgdata.tar.gz -C /data
Bei einer Live-Datenbank kann das Kopieren solcher Dateien zu einem inkonsistenten Zustand führen. Stoppen Sie zuerst den Container oder verwenden Sie besser das datenbankeigene Tool, z. B. pg_dump für PostgreSQL. Und ein Backup, das Sie nie wiederhergestellt haben, ist eigentlich nur eine Hoffnung, also testen Sie die Wiederherstellung.
Dateiberechtigungen
„Berechtigung verweigert“ ist das häufigste Problem bei Mounts. Unter Linux behalten Dateien ihre numerischen Benutzer- und Gruppen-IDs. Wenn also ein Container als Benutzer 1000 ausgeführt wird und der Hostordner einem anderen Benutzer gehört, schlagen Schreibvorgänge fehl. Einige Möglichkeiten, dies zu beheben:
- Führen Sie den Container mit einem passenden Benutzer aus:
docker run --user "$(id -u):$(id -g)" ... - Richten Sie den korrekten Besitz für Ihr Image ein, wie in unseren Dockerfile-Best Practices beschrieben.
- Bevorzugen Sie benannte Volumes für Daten, da ein neues Volume bei der ersten Verwendung den Besitz des Image-Ordners übernimmt.
- Auf Systemen, die SELinux verwenden, benötigen Bind-Mounts möglicherweise die Bezeichnung
:zoder:Z.
Vermeiden Sie die Versuchung von chmod 777, wie unser Leitfaden zu Linux-Befehlen erklärt.
Welches sollten Sie verwenden?
| Situation | Benutzen |
|---|---|
| Datenbankdaten | Benannter Datenträger |
| Live-Bearbeitung des Quellcodes | Halterung binden |
| Eine Konfigurationsdatei aus Ihrem Repository | Schreibgeschützter Bind-Mount |
| Datenaustausch zwischen Containern | Benannter Datenträger |
| Temporäre Cache- oder Scratch-Dateien | tmpfs |
| Wegwerf-Testdatenbank | tmpfs oder kein Mount |
| Anwendungscode in der Produktion | Bauen Sie es in das Bild ein |
Die letzte Reihe ist wichtig. In der Produktion gehört der Code in das Image, sodass Sie auch das ausführen, was Sie getestet haben. In Clustern funktioniert die Datenspeicherung wiederum anders, und zwar über persistente Volumes, die in der umfassenderen Kubernetes-Dokumentation behandelt werden. Unser Leitfaden Docker vs. Kubernetes erklärt, wie die beiden zusammenhängen.
Häufige Fehler
- Bereitstellung auf dem falschen Pfad. Die Daten befinden sich immer noch in der Containerschicht und verschwinden später.
- Wird
down -vbeiläufig ausgeführt. Dadurch werden Ihre benannten Volumes gelöscht. - Verwendung relativer Pfade mit
-v. Formulare wie-v data:/xerstellen ein Volume statt einer Ordnerzuordnung. - Geheimnisse in beschreibbare Bind-Mounts einfügen. Hängen Sie sie schreibgeschützt ein oder verwenden Sie eine Geheimnisfunktion.
- Zwei Datenbankcontainer auf ein Volume verweisen. Dies kann die Daten beschädigen.
- Keine Backups vorhanden. Ein Volume ist kein Backup. Es lebt auf derselben Festplatte.
Fazit
Die Faustregel ist kurz: benannte Volumes für Daten, Bind-Mounts für Code, den Sie bearbeiten, und tmpfs für Dinge, die nicht von Dauer sein sollten. Versuchen Sie es mit einer Wegwerfdatenbank. Erstellen Sie ein benanntes Volume, fügen Sie eine Zeile hinzu, löschen Sie den Container, starten Sie einen neuen und bestätigen Sie, dass Ihre Zeile erhalten geblieben ist. Üben Sie dann ein Backup und eine Wiederherstellung, bevor Sie eines benötigen.
Häufige Fragen
Was ist der Unterschied zwischen einem Docker-Volume und einem Bind-Mount?
Ein Volume wird von Docker verwaltet und in einem eigenen Bereich gespeichert. Ein Bind-Mount ordnet einen bestimmten Hostpfad, den Sie steuern, direkt dem Container zu.
Werden durch das Stoppen eines Containers dessen Daten gelöscht?
Nein. Daten in der beschreibbaren Ebene überstehen einen Stopp und Neustart. Es geht verloren, wenn der Container entfernt wird, es sei denn, es wird in einem Volume oder Bind-Mount gespeichert.
Bleiben Docker-Volumes bestehen, nachdem Docker heruntergefahren wurde?
Ja, benannte Volumes bleiben nach dem Herunterfahren durch Docker bestehen. Durch Hinzufügen des Flags -v werden sie zusammen mit allen darin enthaltenen Daten gelöscht.
Wo werden Docker-Volumes gespeichert?
Unter Linux normalerweise unter /var/lib/docker/volumes. Auf Docker Desktop leben sie in einer virtuellen Maschine. Verwenden Sie Docker Volume Inspect, um den Speicherort anzuzeigen.
Können sich mehrere Container ein Volume teilen?
Ja, mehrere Container können ein Volume bereitstellen. Die Anwendung muss den gleichzeitigen Zugriff sicher verarbeiten, und Datenbanken sollten Datendateien im Allgemeinen nicht auf diese Weise gemeinsam nutzen.
Lerne weiter
Benötigen Sie Hilfe beim Testen, WordPress oder SEO?
Wir helfen Teams, bessere Software zu liefern und ihre Websites zu erweitern. Sagen Sie uns, woran Sie gerade arbeiten, und wir schlagen Ihnen einen klaren nächsten Schritt vor.
Weitere Anleitungen finden Sie unter Tests, KI und moderne Entwicklung
Hat Ihnen dieser Artikel gefallen? Wählen Sie ein Thema und springen Sie direkt in unsere neuesten Tutorials.
KI-Halluzinationen erklärt: Warum Sprachmodelle Dinge erfinden und wie man sie reduziert
KI-Halluzinationen erklärt: Was sie sind, warum Sprachmodelle sie produzieren, gängige Typen, wie man sie mit Erdung und Eingabeaufforderungen reduz…
Artikel lesen →DevOpsErklärte Umgebungsvariablen: .env-Dateien, Geheimnisse und Konfiguration richtig gemacht
Umgebungsvariablen anhand von Python-Beispielen erklärt, die wir ausgeführt haben: Sie lesen und festlegen, warum jeder Wert ein String ist, .env-Da…
Artikel lesen →SoftwareentwicklungAPI-Ratenbegrenzung erklärt: Algorithmen, Header und Behandlung von 429-Fehlern
API-Ratenbegrenzung anhand einer von uns durchgeführten Simulation erklärt: Token-Bucket, festes Fenster, gleitendes Fenster, 429 Antworten, Ratenbe…
Artikel lesen →TestautomatisierungSpott in Python: unittest.mock, Patch und die Fehler, die Tests zum Lügen machen
Mocking in Python mit unittest.mock, getestet: Mock und return_value, side_effect, Patchen, wo ein Name verwendet wird, Spezifikation und Autospec, …
Artikel lesen →SoftwaretestsCode-Abdeckung erklärt: Leitungs- und Zweigstellenabdeckung und was 100 % wirklich bedeutet
Erklärung der Codeabdeckung anhand eines echten Coverage.py-Laufs: Zeilen-, Zweig- und Bedingungsabdeckung, Lesen eines Berichts, warum bei 100 % Ab…
Artikel lesen →Datenbanken & SQLDELETE vs. TRUNCATE vs. DROP in SQL: Unterschiede, Rollback und Verwendungszweck
DELETE vs. TRUNCATE vs. DROP erklärt mit getestetem SQL: was jeweils entfernt wird, Rollback, Trigger, Identitätsrücksetzung, Geschwindigkeit und wi…
Artikel lesen →Datenbanken & SQLErklärte SQL-Ansichten: Erstellen, nutzen und vermeiden Sie Fallstricke mit Beispielen
SQL-Ansichten anhand der von uns ausgeführten Abfragen erklärt: Erstellen einer Ansicht, Live-Ergebnisse, Ausblenden von Spalten, Leistung, aktualis…
Artikel lesen →SoftwareentwicklungTypeScript-Schnittstelle vs. Typ: Echte Unterschiede, getestet mit dem Compiler
TypeScript-Schnittstelle vs. Typ, überprüft mit dem echten Compiler: Was beide können, was nur einer kann, Deklarationszusammenführung, Erweiterunge…
Artikel lesen →SoftwareentwicklungPython *args und **kwargs erklärt: Flexible Funktionen mit klaren Beispielen
Python *args und **kwargs erklärt mit Code, den wir ausgeführt haben: Packen und Entpacken, Parameterreihenfolge, Nur-Schlüsselwort- und Nur-Positio…
Artikel lesen →SoftwareentwicklungPython-Lambda-Funktionen: Syntax, tatsächliche Verwendung und wann man sie nicht verwendet
Python-Lambda-Funktionen erklärt mit Code, den wir ausgeführt haben: Syntax, Sortierung mit Schlüssel, Karte und Filter, Abschlüsse, die Late-Bindin…
Artikel lesen →Künstliche IntelligenzWas sind KI-Agenten? Wie sie funktionieren, mit einer einfachen Agentenschleife, die Sie ausführen können
Was sind KI-Agenten? Eine einfache Anleitung zur Agentenschleife, zu Tools, Speicher und Leitplanken, mit einer kleinen Python-Schleife, die wir aus…
Artikel lesen →DevOpsÜberwachung vs. Beobachtbarkeit: Der wahre Unterschied, mit Protokollen, Metriken und Traces
Überwachung vs. Beobachtbarkeit erklärt: bekannte und unbekannte Fehler, Protokolle, Metriken und Spuren, eine exemplarische Vorgehensweise für Chec…
Artikel lesen →DevOpsDocker-Volumes vs. Bind Mounts: Containerdaten auf die richtige Art und Weise beibehalten
Docker-Volumes vs. Bind-Mounts erklärt: Warum Containerdaten verschwinden, benannte Volumes, Bind-Mounts, tmpfs, Compose-Beispiele, Backups, Berecht…
Artikel lesen →TestautomatisierungTDD vs. BDD: Hauptunterschiede, eine Funktion, die auf beide Arten entwickelt wurde und wann sie jeweils verwendet werden sollte
TDD vs. BDD erklärt mit einer Rabattfunktion, die in beide Richtungen aufgebaut ist: Rot-Grün-Refaktor mit Code, den wir ausgeführt haben, Gegeben-W…
Artikel lesen →SoftwareentwicklungGit merge vs rebase: Unterschiede, Beispiele und wann man was nutzt
Git merge vs rebase erklärt mit echter Log-Ausgabe, einer Vergleichstabelle, der goldenen Regel des Rebase und einem sicheren Team-Workflow.
Artikel lesen →SoftwareentwicklungPython List Comprehension: Syntax, Beispiele und wann man darauf verzichtet
Python List Comprehension erklärt: Syntax, Filter, if-else, verschachtelte Schleifen, gemessene Zeiten und Fälle, in denen eine normale for-Schleife…
Artikel lesen →Datenbanken & SQLSQL Joins erklärt mit Beispielen (Inner, Left, Right, Full)
SQL Joins Schritt für Schritt mit Beispieltabellen und Abfragen verstehen: INNER, LEFT, RIGHT, FULL, CROSS und SELF, plus typische Fehler und Perfor…
Artikel lesen →