Wenn ich mit Docker starte, ist alles erstmal schön: Container hochfahren, App läuft, fertig. Der Moment, in dem ich wirklich verstanden habe, warum man Docker Volumes braucht, kam aber erst später – als ich gemerkt habe: Container sind flüchtig. Ich kann sie stoppen, löschen, neu erstellen … und wenn meine Daten „im Container“ liegen, sind sie im Zweifel weg.
Volumensind für mich die Antwort darauf: Sie entkoppeln Daten vom Container-Lifecycle. Und genau darum geht’s hier: Was Volumes sind, wann ich sie nutze, wie ich sie erstelle – und welche typischen Fallen ich vermeide.
Warum Docker Volumes überhaupt?
Ein Container ist für mich wie ein Wegwerf-Objekt: ich kann ihn jederzeit ersetzen. Das ist auch gut so – aber nur, wenn meine Daten nicht an ihn gebunden sind.
Typische Beispiele, wo ich persistente Daten brauche:
- Datenbanken (PostgreSQL, MySQL, MariaDB)
- Uploads (z.B. Bilder aus einem CMS)
- Logs, die ich über Container-Neustarts hinweg behalten will
- Konfigurationen oder Zertifikate, die nicht ins Image gehören
Mit Volumes kann ich Daten so speichern, dass ich Container zerstören kann, ohne Inhalte zu verlieren.
Die 3 Speicher-Optionen in Docker (so unterscheide ich sie)
- Container-Dateisystem: schnell, aber flüchtig – weg, wenn Container weg ist
- Bind Mounts: Ordner vom Host wird in den Container gemountet (sehr direkt)
- Docker Volumes: von Docker verwalteter Speicherbereich (mein Standard für Persistenz)
Ich setze in der Praxis am häufigsten auf Docker Volumes, weil sie sauberer, portabler und einfacher zu verwalten sind als Bind Mounts – vor allem im Team oder auf Servern.
Was ist ein Docker Volume?
Ein Volume ist ein Speicherbereich, den Docker verwaltet. Ich kann ihn einem oder mehreren Containern „einstecken“ (mounten). Lösche ich den Container, bleibt das Volume bestehen – bis ich es aktiv entferne.
Volume erstellen und nutzen (mein Standard-Workflow)
1) Volume anlegen
docker volume create mydata
2) Volumes auflisten
docker volume ls
3) Details ansehen
docker volume inspect mydata
Ich schaue hier gerne auf den Mountpoint, um zu verstehen, wo Docker die Daten tatsächlich ablegt.
Beispiel: PostgreSQL mit Volume (Datenbankdaten bleiben erhalten)
Das ist so ziemlich mein häufigster Use Case: eine DB im Container – aber die Daten dauerhaft im Volume.
docker volume create pgdata
docker run -d \
--name postgres \
-e POSTGRES_PASSWORD=secret \
-p 5432:5432 \
-v pgdata:/var/lib/postgresql/data \
postgres:16
Was passiert hier?
- Postgres speichert Daten in
/var/lib/postgresql/data - Ich mounte dort ein Volume hin
- Stoppe/lösche ich den Container, bleibt
pgdatabestehen
Test: Container löschen – Daten bleiben
docker stop postgres
docker rm postgres
Jetzt erstelle ich ihn neu (mit gleichem Volume):
docker run -d \
--name postgres \
-e POSTGRES_PASSWORD=secret \
-p 5432:5432 \
-v pgdata:/var/lib/postgresql/data \
postgres:16
In der Praxis ist das genau der Punkt, an dem ich mir denke: Okay, jetzt macht Docker wirklich Sinn.
Named Volume vs. Anonymous Volume (mein Merksatz)
In Docker gibt es Volumes mit Namen und „anonyme“ Volumes.
- Named Volume (empfohlen):
-v pgdata:/path - Anonymous Volume (passiert schnell aus Versehen):
-v /path
Mein Merksatz: Wenn mir Daten wichtig sind, gebe ich dem Volume immer einen Namen. Sonst verliere ich schnell den Überblick.
Bind Mounts vs. Volumes (wann ich was nutze)
Ich nutze Bind Mounts, wenn …
- ich lokal entwickle und Quellcode live im Container brauche
- ich bewusst auf Host-Dateien zugreifen will
docker run -it --rm \
-v "$(pwd)":/app \
-w /app \
node:20 bash
Ich nutze Volumes, wenn …
- es um Persistenz geht (DB, Uploads, Daten)
- ich keine Lust auf Host-Pfad-Chaos habe
- das Setup portabel bleiben soll
Ein Volume in Docker Compose (so schreibe ich es fast immer)
Wenn ich mit docker compose arbeite, definiere ich Volumes in der compose.yml. Beispiel mit PostgreSQL:
services:
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: secret
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
Das ist für mich der „saubere Standard“: ein benanntes Volume, klar dokumentiert, teamfähig.
Backup & Restore: So sichere ich ein Docker Volume (mein pragmatischer Ansatz)
Wenn ich Daten aus einem Volume sichern will, nutze ich gerne einen temporären Container, der das Volume mountet und ein Archiv erstellt.
Backup erstellen
docker run --rm \
-v pgdata:/data \
-v "$(pwd)":/backup \
alpine \
sh -c "tar czf /backup/pgdata-backup.tar.gz -C /data ."
Restore zurückspielen
docker run --rm \
-v pgdata:/data \
-v "$(pwd)":/backup \
alpine \
sh -c "rm -rf /data/* && tar xzf /backup/pgdata-backup.tar.gz -C /data"
Hinweis: Bei Datenbanken sichere ich produktiv meistens logisch (z.B. pg_dump) statt Dateisystem-Snapshot. Aber fürs schnelle Lab/Dev-Setup ist das super.
Aufräumen: ungenutzte Volumes finden und löschen
Manchmal sammelt sich Müll an – vor allem, wenn ich viel teste. Dann schaue ich mir ungenutzte Volumes an:
docker volume ls
Und entferne gezielt:
docker volume rm mydata
Oder ich lasse Docker ungenutzte Volumes aufräumen:
docker volume prune
Wichtig: prune löscht nur Volumes, die aktuell von keinem Container verwendet werden. Trotzdem: Ich nutze es mit Respekt.
Typische Fehler, die ich heute vermeide
- Daten „im Container“ speichern und dann überrascht sein, dass sie weg sind
- Anonyme Volumes nutzen und später nicht mehr wissen, welches Volume zu welchem Projekt gehört
- Bind Mounts im Serverbetrieb nutzen, obwohl ein Volume sauberer wäre
- Backups vergessen (Volumes sind nicht automatisch gesichert!)
Fazit
Docker Volumes sind für mich der Schlüssel, um Container wirklich sinnvoll im Alltag zu nutzen. Denn erst wenn Daten dauerhaft gespeichert sind, kann ich Container ohne Angst neu bauen, ersetzen und skalieren.