Docker-Volumes vs. Bind Mounts: Containerdaten auf die richtige Art und Weise beibehalten

  1. Startseite
  2. Blog
  3. DevOps

DevOps

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.

9 Min. Lesezeit
Docker-Volumes vs. Bind-Mounts: Containerdaten auf die richtige Weise beibehalten

Das Wichtigste

  • 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 -v lö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 /app montieren, wird alles, was sich im Bild befand, unsichtbar. Ein häufiges Beispiel ist das Verschwinden von node_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 :z oder :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 -v beiläufig ausgeführt. Dadurch werden Ihre benannten Volumes gelöscht.
  • Verwendung relativer Pfade mit -v. Formulare wie -v data:/x erstellen 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

Arbeiten Sie mit Stack Quora

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.

Lesen Sie weiter

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.

Künstliche Intelligenz

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 →
DevOps

Erklä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 →
Softwareentwicklung

API-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 →
Testautomatisierung

Spott 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 →
Softwaretests

Code-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 & SQL

DELETE 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 & SQL

Erklä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 →
Softwareentwicklung

TypeScript-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 →
Softwareentwicklung

Python *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 →
Softwareentwicklung

Python-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 Intelligenz

Was 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 →
DevOps

Docker-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 →
Testautomatisierung

TDD 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 →
Softwareentwicklung

Git 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 →
Softwareentwicklung

Python 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 & SQL

SQL 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 →