Docker · Storage · DevOps · Compose
Docker Volumes vs. Bind Mounts
wann was wirklich richtig ist

Named Volumes, Bind Mounts und tmpfs lösen unterschiedliche Probleme – und die falsche Wahl kostet Datenverlust, Rechtechaos oder Produktionsausfälle. Dieser Artikel zeigt die genauen Unterschiede, die Entscheidungslogik hinter Docker Volumes und Bind Mounts sowie die Compose-Konfigurationen, die in echten Projekten wirklich funktionieren.

12 Min. Lesezeit Named Volumes · Bind Mounts · tmpfs · Compose · Backup Docker 24+ · Compose v2 · Linux · macOS

1. Das Storage-Modell von Docker verstehen

Container sind per Design ephemer – ihr beschreibbares Layer existiert nur so lange wie der Container selbst. Sobald ein Container entfernt wird, gehen alle Daten verloren, die nicht in einem persistenten Storage-Medium gespeichert sind. Docker löst dieses Problem mit drei Mechanismen: Docker Volumes, Bind Mounts und tmpfs-Mounts. Alle drei haben dasselbe Ziel – Daten über den Container-Lebenszyklus hinaus verfügbar zu machen oder gezielt außerhalb des Image-Layers zu halten – aber sie unterscheiden sich fundamental in Verhalten, Performance und Anwendungsfall.

Das Verständnis dieser Unterschiede ist keine akademische Übung. In der Praxis beobachtet man wiederholt dieselben Fehler: Datenbankdaten in Bind Mounts mit Rechteproblemen, Quellcode in Named Volumes mit veralteten Inhalten, Secrets in regulären Mounts statt in tmpfs. Jeder dieser Fehler hat direkte Auswirkungen auf den Betrieb – Datenverluste beim Update, Rechteprobleme im Team-Setup oder Sicherheitslücken in der Produktionsinfrastruktur. Die richtige Wahl zwischen Docker Volumes und Bind Mounts ist deshalb eine der fundamentalen Entscheidungen beim Containerisieren einer Anwendung.

Docker verwaltet Docker Volumes vollständig selbst, unabhängig von der Host-Verzeichnisstruktur. Bind Mounts binden einen konkreten Host-Pfad in den Container ein – der Pfad muss auf dem Host existieren. tmpfs-Mounts leben ausschließlich im Arbeitsspeicher des Hosts und werden nie auf Disk geschrieben. Diese drei grundlegenden Eigenschaften bestimmen alles Weitere: Portabilität, Performance, Sicherheit und Wartbarkeit.

2. Named Volumes: Daten ohne Hostpfad-Abhängigkeit

Docker Volumes – genauer: Named Volumes – sind der empfohlene Standardmechanismus für persistente Daten in Produktionsumgebungen. Docker erstellt und verwaltet sie in einem eigenen Verzeichnis auf dem Host (standardmäßig /var/lib/docker/volumes/), das vollständig unter Docker-Kontrolle steht. Der entscheidende Vorteil: Named Volumes sind von der Host-Verzeichnisstruktur entkoppelt. Ein Compose-Projekt läuft auf jedem Linux-Host mit Docker-Installation gleich, ohne dass bestimmte Pfade existieren müssen.

Named Volumes haben gegenüber Bind Mounts einen weiteren praktischen Vorteil bei der Initialisierung: Wenn ein Docker Volume beim ersten Start noch leer ist, kopiert Docker den Inhalt des entsprechenden Image-Verzeichnisses hinein. Bei einer PostgreSQL-Installation bedeutet das, dass /var/lib/postgresql/data aus dem Image initial in das Volume übertragen wird – die Datenbank initialisiert sich korrekt. Bei einem Bind Mount auf ein leeres Verzeichnis überschreibt der leere Host-Ordner den Image-Inhalt, was zu einem Startfehler führt. Dieser Unterschied überrascht viele beim ersten Mal.

Die Lebenszeit eines Named Volume ist explizit: Es existiert bis es mit docker volume rm oder docker compose down -v gelöscht wird. Ein docker compose down ohne -v lässt Docker Volumes unangetastet – Datenbankdaten, Uploads und andere persistente Daten bleiben erhalten, auch wenn alle Container gestoppt und entfernt wurden. Das ist das erwünschte Verhalten für Produktion, erfordert aber im Entwicklungsalltag Bewusstsein für den Flag.

3. Bind Mounts: Quellcode und Konfiguration direkt einbinden

Bind Mounts binden ein Verzeichnis oder eine Datei vom Host direkt in den Container ein. Was auf dem Host liegt, ist sofort im Container sichtbar – und umgekehrt. Das macht Bind Mounts zum idealen Werkzeug für die lokale Entwicklung: Der Quellcode liegt auf dem Entwickler-Laptop, der Container sieht Änderungen in Echtzeit, ohne dass ein Rebuild nötig ist. Dieses Muster ist in praktisch jedem Docker-basierten Entwicklungssetup zu finden und ist für diesen Zweck die richtige Wahl.

Im Gegensatz zu Docker Volumes sind Bind Mounts unmittelbar an die Host-Verzeichnisstruktur gebunden. Das bringt Portabilitätsprobleme: Ein docker-compose.yml mit absolutem Pfad /home/alice/project funktioniert auf einem anderen Rechner oder in CI nicht ohne Anpassung. Relative Pfade wie ./src lösen das für einfache Fälle, aber die Abhängigkeit vom exakten Ausführungsverzeichnis bleibt. In Produktionsumgebungen, wo Pfade zwischen Deployment-Systemen variieren können, ist das ein Risiko.

Ein weiteres Problem von Bind Mounts in Produktion: Die Verzeichnisberechtigungen auf dem Host bestimmen, was der Container-Prozess lesen und schreiben kann. Wenn der Container-Prozess als UID 1000 läuft, der Host-Ordner aber root gehört, entstehen Schreibfehler. Wenn umgekehrt der Container-Prozess als root läuft und Dateien in einen gemounteten Host-Ordner schreibt, entstehen dort Dateien, die dem Entwickler-Benutzer auf dem Host nicht gehören. Dieses Rechtechaos ist bei Bind Mounts strukturell bedingt und eine der häufigsten Supportfragen in Teams.

4. tmpfs-Mounts: flüchtiger Arbeitsspeicher für sensible Daten

tmpfs-Mounts sind die dritte Option und die am wenigsten bekannte. Sie legen ein temporäres Dateisystem im Arbeitsspeicher des Hosts an. Daten in einem tmpfs-Mount werden nie auf Disk geschrieben – weder auf den Host noch in das Container-Layer. Das macht tmpfs-Mounts zur richtigen Wahl für sensible temporäre Daten: Secrets, Session-Tokens, private Schlüssel während der Laufzeit, temporäre Berechnungsergebnisse. Wird der Container gestoppt oder der Host neu gestartet, sind die Daten unwiderruflich weg.

In der Praxis sind tmpfs-Mounts besonders relevant für Sicherheitsanforderungen. Wer sicherstellen will, dass ein Secret niemals in einer Logdatei, auf einem Volume-Backup oder in einem Container-Diff auftaucht, greift zu tmpfs. Die Performance ist dabei oft besser als bei Disk-basierten Mounts, da der Kernel direkt aus dem RAM bedient. Für PHP-Session-Dateien, für temporäre Kryptoschlüssel oder für Build-Artefakte, die nach dem Build-Schritt keine Rolle mehr spielen, ist tmpfs die elegante Lösung.


# Named Volume — Docker manages storage location on the host
docker volume create myapp_db_data

# Inspect volume: shows actual storage path under /var/lib/docker/volumes/
docker volume inspect myapp_db_data

# Bind Mount — directly maps host path into container
docker run -v /home/dev/project/src:/var/www/html myapp:latest

# tmpfs Mount — in-memory only, never written to disk
docker run --tmpfs /tmp:rw,noexec,nosuid,size=128m myapp:latest

# Compose: Named Volume with custom driver options
# services.db.volumes uses top-level volumes block
docker compose up -d            # volumes are created automatically
docker compose down             # volumes are KEPT — data persists
docker compose down -v          # volumes are REMOVED — data is gone

5. Docker Volumes vs. Bind Mounts im direkten Vergleich

Die Wahl zwischen Docker Volumes und Bind Mounts ist keine Frage des persönlichen Geschmacks, sondern eine Frage des Anwendungsfalls. Named Volumes gewinnen bei Portabilität, Initialisierungsverhalten und Produktionssicherheit. Bind Mounts gewinnen bei Entwicklungskomfort und direktem Dateizugriff vom Host. Die folgende Tabelle fasst die wichtigsten Unterschiede zusammen.

Kriterium Named Volume Bind Mount tmpfs
Persistenz Ja, bis explizit gelöscht Ja, Host-Datei bleibt Nein – RAM, verloren bei Stop
Portabilität Hoch – kein Hostpfad nötig Gering – Pfad muss existieren Hoch – nur RAM-Verfügbarkeit
Initialisierung Image-Inhalt wird kopiert Host überschreibt Image-Inhalt Leer bei Start
Dateirechte Docker verwaltet Ownership Host-UID/GID kann kollidieren Mount-Optionen steuerbar
Performance (Linux) Native, kein Overhead Native (Linux), langsam (macOS) Schnellster Typ
Empfohlener Einsatz Datenbanken, Uploads, Produktion Quellcode, lokale Entwicklung Secrets, Session, Temp-Daten

Ein oft übersehener Punkt: Auf macOS und Windows läuft Docker nicht nativ, sondern in einer Linux-VM. Bind Mounts müssen durch diese VM-Grenze übertragen werden, was erhebliche Performance-Einbußen verursacht – besonders bei Projekten mit vielen kleinen Dateien wie PHP-Anwendungen mit tausenden .php-Dateien im Vendor-Verzeichnis. Docker Volumes leben innerhalb der VM und haben diesen Cross-VM-Overhead nicht. Das ist der Hauptgrund, warum in modernen Docker-Desktop-Setups auf macOS die Empfehlung lautet, Abhängigkeitsverzeichnisse wie vendor oder node_modules als Named Volume zu mounten statt als Bind Mount.

6. Compose-Konfigurationen für alle drei Typen

Docker Compose bietet eine deklarative Syntax für alle drei Storage-Typen. Named Volumes werden im Top-Level volumes-Block deklariert und in Services referenziert. Bind Mounts werden direkt als Pfad-Paar in der volumes-Liste eines Services angegeben. Für tmpfs gibt es einen eigenen tmpfs-Schlüssel auf Service-Ebene. Die Unterscheidung zwischen Docker Volumes und Bind Mounts erfolgt in Compose automatisch: Enthält der Source-Pfad einen / oder beginnt mit ./, ist es ein Bind Mount. Ein Name ohne Pfadseparator ist ein Named Volume.


# compose.yaml — All three storage types in one file
services:
  db:
    image: mysql:8.4
    volumes:
      # Named Volume: Docker manages /var/lib/docker/volumes/myapp_db_data
      - db_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password

  app:
    image: myapp:latest
    volumes:
      # Bind Mount: host source code in container, editable in real time
      - ./src:/var/www/html/src:ro
      # Named Volume: vendor dir lives inside VM — no cross-VM overhead on macOS
      - vendor_cache:/var/www/html/vendor
      # tmpfs: PHP session files never hit disk
    tmpfs:
      - /var/www/html/var/session:size=64m,mode=1777

  redis:
    image: redis:7-alpine
    volumes:
      # Named Volume for RDB snapshots — portable between environments
      - redis_data:/data

# Top-level volumes block — volumes are created if they don't exist
volumes:
  db_data:
    driver: local
  vendor_cache:
    driver: local
  redis_data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /mnt/fast-ssd/redis  # optional: place on specific storage device

Ein wichtiges Detail beim Compose-Syntax: Die erweiterte Volume-Schreibweise mit type, source und target ist expliziter und vermeidet Mehrdeutigkeiten. Bei komplexen Projekten mit vielen Volumes empfiehlt sich diese Form gegenüber der Kurznotation. Für Read-only-Mounts – etwa Konfigurationsdateien, die ein Container lesen aber nicht ändern soll – wird :ro als viertes Element oder als read_only: true in der erweiterten Form angegeben. Das verhindert, dass ein kompromittierter Container-Prozess Konfigurationsdateien auf dem Host verändert.

7. Dateirechte und UID/GID-Konflikte lösen

Dateirecht-Konflikte bei Bind Mounts sind das häufigste praktische Problem im Team-Entwicklungssetup. Die Ursache ist strukturell: Der Container-Prozess läuft unter einer bestimmten UID, der Host-Benutzer hat eine andere UID, und Linux prüft Dateizugriffsrechte anhand der numerischen UID – nicht anhand von Benutzernamen. Wenn der Nginx-Prozess im Container als UID 101 läuft und die gemounteten Logverzeichnisse dem Host-Benutzer mit UID 1000 gehören, entstehen Permission-Denied-Fehler. Dieser Konflikt tritt besonders häufig auf, wenn Teams auf verschiedenen Systemen arbeiten oder wenn CI-Systeme Container mit anderen UID-Defaults verwenden.

Die saubersten Lösungsansätze für Bind-Mount-Rechtekonflikte: In Dockerfile eine UID definieren, die mit dem Entwickler-Benutzer übereinstimmt, oder den Container-Prozess mit user: "${UID}:${GID}" in Compose unter der UID des Host-Benutzers starten. Für Docker Volumes entfällt dieses Problem weitgehend, da Docker die Ownership im Volume selbst verwaltet und der Image-initiale Inhalt mit den korrekten Rechten übertragen wird. Ein weiterer Ansatz für kritische Produktionsszenarien: ein Init-Container, der in einem entrypoint.sh via chown die Rechte im Volume korrigiert, bevor der eigentliche Prozess startet.


# Dockerfile: set a specific UID to avoid conflicts with host user
FROM php:8.4-fpm-alpine

# Create app user with UID 1000 — matches typical Linux developer user
RUN addgroup -g 1000 app && adduser -u 1000 -G app -D app

# Set correct ownership inside the image
WORKDIR /var/www/html
RUN chown -R app:app /var/www/html

USER app

# compose.yaml: override user at runtime to match host UID dynamically
services:
  app:
    image: myapp:latest
    # Pass host UID/GID via environment — set in shell: export UID GID
    user: "${UID:-1000}:${GID:-1000}"
    volumes:
      - ./src:/var/www/html/src

# Fix-ownership init pattern for Named Volumes in production
services:
  app:
    image: myapp:latest
    entrypoint: ["/docker-entrypoint.sh"]
    volumes:
      - app_data:/var/www/html/var

# In docker-entrypoint.sh:
# chown -R app:app /var/www/html/var && exec "$@"

8. Backup und Restore von Docker Volumes

Named Volumes sind von der Host-Verzeichnisstruktur entkoppelt, was Backups nicht offensichtlich, aber sehr zuverlässig macht. Das Standardmuster für Volume-Backups ist ein temporärer Backup-Container, der das zu sichernde Volume einbindet und den Inhalt per tar in ein gemountetes Backup-Verzeichnis schreibt. Docker stellt dafür keine eigene Backup-Funktion bereit – das Muster mit einem temporären BusyBox- oder Alpine-Container ist die empfohlene Praxis aus der offiziellen Dokumentation. Wichtig: Für Datenbanken, die transaktionale Konsistenz erfordern, muss vor dem Volume-Backup entweder die Datenbank gestoppt oder ein datenbankspezifisches Dump-Werkzeug genutzt werden.

Der Restore-Prozess ist das genaue Umkehrverfahren: Ein leeres Docker Volume erstellen, einen temporären Container mit beiden Mounts starten – dem Backup-Verzeichnis als Bind Mount und dem Ziel-Volume als Named Volume – und den tar-Stream wieder entpacken. Dieser Prozess ist vollständig skriptierbar und eignet sich für Cron-Jobs, CI-Pipelines und manuelle Notfallwiederherstellungen. Wer Volumes zwischen Hosts migrieren muss, exportiert den tar-Stream, überträgt ihn per scp oder rsync und importiert ihn auf dem Zielsystem in ein neues Volume.


#!/usr/bin/env bash
# backup-volume.sh — Backup a Docker Named Volume to a tar.gz file
set -euo pipefail

VOLUME_NAME="${1:?Usage: $0 <volume-name> <backup-dir>}"
BACKUP_DIR="${2:?Usage: $0 <volume-name> <backup-dir>}"
TIMESTAMP="$(date +%Y%m%d-%H%M%S)"
BACKUP_FILE="${BACKUP_DIR}/${VOLUME_NAME}-${TIMESTAMP}.tar.gz"

mkdir -p "$BACKUP_DIR"

echo "[INFO] Backing up volume: $VOLUME_NAME"

# Run temporary Alpine container — mounts volume read-only, backup dir writable
docker run --rm \
  -v "${VOLUME_NAME}:/source:ro" \
  -v "${BACKUP_DIR}:/backup" \
  alpine:3 \
  sh -c "tar -czf /backup/$(basename "$BACKUP_FILE") -C /source ."

echo "[OK] Backup written to: $BACKUP_FILE"

# Restore pattern — pipe directly without intermediate file
restore_volume() {
  local backup_file="$1"
  local target_volume="$2"

  # Create volume if it doesn't exist
  docker volume create "$target_volume"

  docker run --rm \
    -v "${backup_file%/*}:/backup:ro" \
    -v "${target_volume}:/target" \
    alpine:3 \
    sh -c "tar -xzf /backup/$(basename "$backup_file") -C /target"

  echo "[OK] Volume $target_volume restored from $backup_file"
}

Mironsoft

Docker Storage, Container-Infrastruktur und Deployment-Automatisierung

Docker Storage ohne Datenverlust und Rechtechaos?

Wir analysieren bestehende Docker-Setups, identifizieren falsch konfigurierte Volumes und Bind Mounts und ersetzen fragile Storage-Konfigurationen durch robuste, portable Lösungen – mit vollständiger Backup-Strategie für Produktion und CI.

Storage-Audit

Analyse aller Volume- und Bind-Mount-Konfigurationen auf Datenverlust-Risiken und Rechtekonflikte

Compose-Refactoring

Bind Mounts in Production auf Named Volumes umstellen, tmpfs für sensible Daten einführen

Backup-Automatisierung

Volume-Backup-Skripte, Cron-Integration und Restore-Tests für produktive Datenbanken und Uploads

9. Entscheidungsmatrix: Wann welcher Storage-Typ?

Die Entscheidung zwischen Docker Volumes, Bind Mounts und tmpfs lässt sich auf wenige klare Fragen reduzieren. Das Ergebnis dieser Fragen bestimmt in fast allen Praxisfällen den richtigen Typ. Die Matrix gilt sowohl für docker run als auch für Compose-Projekte.

Grundregel: Wenn Daten zwischen Container-Neustarts erhalten bleiben müssen und von keinem Prozess außerhalb von Docker direkt zugegriffen wird – Named Volume. Wenn der Host-Prozess oder der Entwickler direkten Zugriff auf dieselben Dateien braucht – Bind Mount, aber nur in Entwicklung. Wenn Daten ausschließlich für die Laufzeit eines Containers existieren sollen und nie auf Disk landen dürfen – tmpfs. Eine häufige Kombination in PHP-Projekten: Docker Volume für die MySQL-Daten, Bind Mount für den Quellcode in Entwicklung (aber nicht in Produktion), tmpfs für PHP-Sessions und temporäre Upload-Zwischenspeicher.

10. Zusammenfassung

Die Wahl zwischen Docker Volumes und Bind Mounts hat direkte Auswirkungen auf Portabilität, Datensicherheit und Betriebssicherheit. Named Volumes sind der richtige Standard für alle persistenten Daten in Produktion: Datenbanken, Upload-Verzeichnisse, Cache-Stores, Redis-Snapshots. Sie sind von der Host-Infrastruktur entkoppelt, initialisieren sich korrekt aus dem Image-Inhalt und werden von Docker konsistent verwaltet. Bind Mounts gehören in die Entwicklungsumgebung, wo direkter Dateizugriff vom Host und Echtzeit-Änderungen im Container wichtig sind – aber nicht in Produktions-Compose-Dateien.

tmpfs-Mounts sind kein Nischenthema, sondern die sicherste Option für alle Daten, die nie auf Disk landen sollen: Secrets, Session-Daten, temporäre Kryptomaterial. Die Performance-Vorteile von tmpfs – kein Disk-I/O, keine fsync-Latenz – sind ein Bonus. Das wichtigste Takeaway: Docker Volumes, Bind Mounts und tmpfs lösen drei verschiedene Probleme. Wer alle drei kennt und bewusst einsetzt, baut Container-Setups, die in Produktion zuverlässig laufen, im Team funktionieren und sich sicher betreiben lassen.

Docker Volumes vs. Bind Mounts — Das Wichtigste auf einen Blick

Named Volumes

Docker-verwaltete persistente Daten ohne Hostpfad-Abhängigkeit. Richtig für Datenbanken, Uploads, Cache-Stores. Kopiert initialen Image-Inhalt beim ersten Start.

Bind Mounts

Host-Pfad direkt im Container. Richtig für Quellcode in lokaler Entwicklung. Nicht für Produktion – Pfadabhängigkeit und UID/GID-Konflikte sind strukturelle Risiken.

tmpfs-Mounts

RAM-basiert, keine Disk-Schreibzugriffe. Richtig für Secrets, Session-Dateien und temporäre Daten, die nie persistent werden dürfen. Schnellster Storage-Typ.

Backup & Restore

Named Volumes per temporärem Alpine-Container mit tar sichern. Datenbankvolumes nur nach Stop oder mit DB-eigenem Dump sichern – nie als rohen Dateisystem-Snapshot.

11. FAQ: Docker Volumes vs. Bind Mounts

1Was ist der Unterschied zwischen Docker Volume und Bind Mount?
Docker Volumes werden von Docker selbst verwaltet und sind von der Host-Pfadstruktur unabhängig. Bind Mounts verbinden einen konkreten Host-Pfad direkt mit dem Container. Volumes sind portabler und initialisieren sich korrekt aus dem Image.
2Warum startet die Datenbank nicht mit einem Bind Mount auf ein leeres Verzeichnis?
Der leere Host-Ordner überschreibt den Image-Inhalt. Named Volumes kopieren beim ersten Start den Image-Inhalt in das leere Volume – das korrekte Verhalten für Datenbankcontainer wie MySQL oder PostgreSQL.
3Werden Volumes beim docker compose down gelöscht?
Nein. Nur mit dem Flag -v werden Volumes entfernt: docker compose down -v. Ohne diesen Flag bleiben Datenbankdaten und alle anderen Volumes unangetastet.
4Wann tmpfs statt Named Volume verwenden?
Wenn Daten niemals auf Disk geschrieben werden dürfen: Secrets, Session-Tokens, temporäre Kryptoschlüssel. tmpfs lebt im RAM und ist nach Container-Stop unwiederbringlich weg.
5Warum sind Bind Mounts auf macOS so langsam?
Docker läuft auf macOS in einer Linux-VM. Bind Mounts traversieren diese VM-Grenze bei jedem Dateizugriff. Named Volumes existieren innerhalb der VM ohne diesen Overhead – für vendor/ und node_modules/ deutlich schneller.
6Wie sichere ich ein Docker Volume?
Temporären Alpine-Container starten, Volume als :ro einbinden, per tar in ein Backup-Verzeichnis schreiben. Für Datenbanken immer den DB-eigenen Dump-Befehl verwenden statt direktem Dateisystem-Backup.
7Wie löse ich UID/GID-Konflikte bei Bind Mounts?
Im Dockerfile eine feste UID (meist 1000) für den App-Prozess definieren, oder in Compose user: "${UID}:${GID}" nutzen. In Produktion Named Volumes bevorzugen – das Problem entfällt dort größtenteils.
8Kann ich ein Named Volume auf eine bestimmte Disk legen?
Ja, mit dem local-Driver und driver_opts: type: none, o: bind, device: /pfad/zur/disk. Das Volume verhält sich nach außen wie ein normales Named Volume, nutzt aber den angegebenen Speicherort.
9Bind Mounts oder Named Volumes in Produktion?
In Produktion ausschließlich Named Volumes für persistente Daten. Quellcode gehört ins Image, nicht als Bind Mount. Nur Konfigurationsdateien können als :ro-Bind-Mount sinnvoll sein – mit UID/GID-Bewusstsein.
10Was passiert mit tmpfs-Daten beim Container-Neustart?
Sie sind verloren. tmpfs-Mounts sind an den laufenden Container gebunden. Beim Stop wird der RAM-Bereich freigegeben – exakt das gewünschte Verhalten für Session-Daten und Secrets.