Zum Inhalt springen
Serverküche
Suche

Die Suche wird geladen … (nur in der veröffentlichten Seite verfügbar).

Grundlagen Schwierigkeit: Einsteiger

Docker-Volumes vs. Bind-Mounts: Wo deine Daten wirklich liegen

Named Volumes oder Bind-Mount? Dieser Grundlagen-Guide erklärt den Unterschied, zeigt beide an echten Beispielen und wann du welches nimmst.

· 7 Min. Lesezeit ·Dauer: ca. 25 Minuten
Inhaltsverzeichnis

Ein Container ist vergänglich: Löschst du ihn, sind seine Daten weg. Damit deine Datenbank, deine Nextcloud-Dateien oder deine Konfiguration ein docker compose down überleben, brauchst du Volumes. Dieser Guide klärt den oft verwirrenden Unterschied zwischen Named Volumes und Bind-Mounts.

Was bauen wir?

Kein neuer Dienst diesmal, sondern ein solides Fundament: Am Ende verstehst du, warum Container-Daten normalerweise verschwinden, kennst die zwei Wege, sie dauerhaft zu speichern, und weißt für jeden Dienst, welchen du nimmst. Alle Beispiele sind mit Docker 29 auf Debian 13 getestet und funktionieren mit jeder aktuellen Docker-Version. Dieses Wissen brauchst du für jedes App-Tutorial – dort taucht in fast jeder compose.yaml ein volumes:-Block auf.

Voraussetzungen

  • Ein Server mit installiertem Docker
  • Grundverständnis von Docker Compose (Services, compose.yaml)
  • Ein Terminal-Zugang zum Server – reine Kommandozeilenübung, keine Web-Oberfläche

Schritt für Schritt

Schritt 1: Warum Container-Daten verschwinden

Alles, was ein Container in sein eigenes Dateisystem schreibt, lebt nur so lange wie der Container. Das ist gewollt – Container sollen austauschbar sein. Für alles, was bleiben soll (Datenbanken, Uploads, Konfiguration), musst du Docker explizit sagen, wo es außerhalb des Containers landet. Genau dafür gibt es zwei Werkzeuge: Named Volumes und Bind-Mounts.

Schritt 2: Named Volumes – von Docker verwaltet

Ein Named Volume ist ein Speicherbereich, den Docker selbst verwaltet. Du gibst ihm nur einen Namen, den Ablageort bestimmt Docker. Leg eines an:

Terminal
docker volume create sk-demo-vol
Ausgabe
sk-demo-vol

Jetzt hängen wir das Volume in einen Wegwerf-Container (--rm löscht ihn danach) unter /data ein und schreiben eine Datei hinein:

Terminal
docker run --rm -v sk-demo-vol:/data alpine:3 sh -c "echo hallo-von-serverkueche > /data/notiz.txt && ls -l /data"
Ausgabe
total 4
-rw-r--r--    1 root     root            23 Jul 20 22:31 notiz.txt

Der Container ist längst weg – die Daten nicht. Wo liegen sie? Frag Docker:

Terminal
docker volume inspect sk-demo-vol --format "{{ .Mountpoint }}"
Ausgabe
/var/lib/docker/volumes/sk-demo-vol/_data

Dieser Pfad gehört Docker. Du kannst ihn als root einsehen, solltest ihn aber nicht direkt bearbeiten:

Terminal
cat /var/lib/docker/volumes/sk-demo-vol/_data/notiz.txt
Ausgabe
hallo-von-serverkueche

Der Beweis für Persistenz: Ein völlig neuer Container sieht dieselben Daten:

Terminal
docker run --rm -v sk-demo-vol:/data alpine:3 cat /data/notiz.txt
Ausgabe
hallo-von-serverkueche

Merke: Named Volumes sind der Standard für Anwendungsdaten – Datenbanken, Uploads, alles, was die App selbst verwaltet. Docker kümmert sich um Ort und Rechte, und das Volume überlebt docker compose down (nur down -v löscht es mit).

Schritt 3: Bind-Mounts – ein Ordner vom Host

Bei einem Bind-Mount hängst du einen konkreten Ordner deines Servers in den Container. Du bestimmst den Pfad, und Änderungen sind sofort auf beiden Seiten sichtbar:

Terminal
mkdir -p /opt/sk-demo-bind
docker run --rm -v /opt/sk-demo-bind:/data alpine:3 sh -c "echo aus-dem-container > /data/host.txt"
ls -l /opt/sk-demo-bind
Ausgabe
total 4
-rw-r--r-- 1 root root 18 Jul 21 00:31 host.txt

Der Container hat die Datei geschrieben, und sie liegt direkt in deinem Host-Ordner – ohne Umweg über /var/lib/docker. Das ist der Sinn von Bind-Mounts: Dateien, die du selbst bearbeiten willst. Klassische Fälle sind Konfigurationsdateien (traefik.yml, nginx.conf) oder eine compose.yaml, die eine Config einliest.

Tipp

Faustregel: Named Volume für Daten, die die App verwaltet (Datenbank, Uploads). Bind-Mount für Dateien, die du verwaltest (Konfiguration). Im Zweifel Named Volume – es macht die wenigsten Rechte-Probleme.

Achtung

Häng niemals sensible Host-Pfade blind in einen Container: nicht /, nicht /etc, keine Home-Verzeichnisse – und ganz besonders nicht /var/run/docker.sock. Wer den Docker-Socket eingehängt bekommt, kann beliebige Container starten und ist damit faktisch root auf dem ganzen Host. Mounte immer nur den einen Ordner, den der Dienst wirklich braucht.

Schritt 4: Beides in der compose.yaml

In Compose sieht der Unterschied so aus. Ein Named Volume wird unten unter volumes: deklariert und oben per Name referenziert; ein Bind-Mount ist einfach ein Host-Pfad:

YAML
services:
  app:
    image: beispiel/app:1
    volumes:
      - app-daten:/var/lib/app                # Named Volume (Docker-verwaltet)
      - ./config.yml:/etc/app/config.yml:ro   # Bind-Mount (deine Datei, read-only)

volumes:
  app-daten:

Das :ro am Ende macht den Bind-Mount read-only – der Container kann die Konfiguration lesen, aber nicht verändern. Für eingehängte Configs ist das eine gute Angewohnheit.

Schritt 5: Die Falle – anonyme Volumes

Lässt du bei -v den Namen weg (-v /data statt -v name:/data) oder bringt ein Image in seinem Dockerfile eine VOLUME-Anweisung mit, entsteht ein anonymes Volume mit einer zufälligen ID. So sieht der erste Fall aus:

Terminal
docker run --name demo -v /data alpine:3 sh -c "echo test > /data/x.txt"

Wir lassen den Container hier bewusst ohne --rm laufen – sonst würde Docker das anonyme Volume beim Beenden sofort mitlöschen. Das Problem im Alltag: Solche Volumes bleiben liegen, sammeln sich unbemerkt an, und du findest später nicht mehr heraus, welche Daten wohin gehören:

Terminal
docker volume ls
Ausgabe
DRIVER    VOLUME NAME
local     sk-demo-vol
local     9f8c1a2b3c4d5e6f70819a0b1c2d3e4f5061a2b3c4d5e6f70819a0b1c2d3e4f50

Die kryptische Zeile ist ein anonymes Volume. Den Wegwerf-Container kannst du jetzt entfernen – das anonyme Volume bleibt trotzdem liegen:

Terminal
docker rm demo

Gib deinen Volumes immer einen Namen – dann bleibt überschaubar, was wozu gehört.

Schritt 6: Volumes verwalten

Die wichtigsten Befehle im Alltag:

Terminal
docker volume ls           # alle Volumes auflisten
docker volume inspect NAME # Details, u. a. Mountpoint
docker volume rm NAME      # ein Volume löschen (Daten weg!)

Das Aufräumen unserer Demo heben wir uns bis nach der Backup-Sektion auf – dort brauchen wir sk-demo-vol nämlich noch.

Wenn es nicht funktioniert

Der Container schreibt, aber der Bind-Mount-Ordner auf dem Host bleibt leer. Du hast einen relativen Pfad benutzt, der woanders zeigt als gedacht, oder Docker hat den Pfad neu als leeren Ordner angelegt. Bei docker run Bind-Mounts immer mit absolutem Pfad angeben (/opt/app/config, nicht config). Existiert dieser Host-Pfad noch nicht, legt Docker ihn stillschweigend als leeren Ordner an – prüfe also mit ls, dass du wirklich den richtigen erwischt hast. In der compose.yaml sind ./-Pfade dagegen völlig in Ordnung – sie sind relativ zur compose.yaml und damit eindeutig. Achtung außerdem: docker run -v config:/data (ohne / oder ./ davor) ist kein Bind-Mount, sondern legt ein Named Volume namens config an.

Permission denied, sobald der Container in den Mount schreiben will. Der Prozess im Container läuft unter einer anderen UID als der Besitzer des Host-Ordners – typisch bei Bind-Mounts. Bei Named Volumes tritt das selten auf (Docker setzt die Rechte). Bei Bind-Mounts den Ordner dem passenden Benutzer geben (chown -R 1000:1000 /opt/app/data) oder im Image die user:-Angabe der Compose nutzen.

Nach docker compose down sind alle Daten weg. Du hast docker compose down -v benutzt – das -v löscht die Named Volumes mit. Für einen normalen Neustart ohne -v arbeiten. -v bewusst nur einsetzen, wenn du wirklich bei null anfangen willst.

docker system prune hat Daten gelöscht. docker volume prune bzw. docker system prune --volumes entfernt Volumes, an denen gerade kein Container hängt. Bei docker volume prune sind benannte Volumes standardmäßig geschützt – gelöscht werden nur anonyme Volumes; benannte fallen erst mit --all/-a weg. (Bei docker system prune steuert -a/--all dagegen die Images, nicht die benannten Volumes.) Ein weiteres starkes Argument fürs Benennen – ein sk-demo-vol übersteht ein versehentliches docker volume prune, ein anonymes Volume nicht. Trotzdem prune mit Volumes nur laufen lassen, wenn alle wichtigen Stacks aktiv sind, oder gezielt mit docker volume rm entfernen.

Wartung & Backups

Volumes sind kein Backup – sie liegen auf derselben Festplatte wie dein Server. Fällt die aus, sind Container und Volume weg. Ein Named Volume sicherst du, indem du seinen Inhalt durch einen Wegwerf-Container in ein Archiv packst:

Terminal
mkdir -p /opt/backups
docker run --rm -v sk-demo-vol:/data -v /opt/backups:/backup alpine:3 \
  tar czf /backup/sk-demo-vol.tar.gz -C /data .

Zurückspielen geht genauso herum – Archiv rein, ins Volume entpacken. Leg das Ziel-Volume vorher an (docker volume create sk-demo-vol) und stopp den zugehörigen Container, damit dir nichts ins offene Volume schreibt:

Terminal
docker run --rm -v sk-demo-vol:/data -v /opt/backups:/backup alpine:3 \
  tar xzf /backup/sk-demo-vol.tar.gz -C /data

Dieses Archiv – und alle Bind-Mount-Ordner unter /opt – gehören in dein verschlüsseltes Off-Site-Backup mit Restic. Damit überlebt deine Datenbank auch einen Totalausfall des Servers.

Im Alltag lohnt sich Ordnung: Benenne Volumes sprechend (nextcloud-db, nicht db), räume anonyme Volumes gelegentlich auf und prüfe mit docker system df, wie viel Platz deine Volumes belegen – gerade bei Datenbanken und Mediendiensten wächst das über die Zeit spürbar.

Zum Schluss räumst du die Demo wieder ab – jetzt, wo Backup und alle Beispiele durch sind:

Terminal
docker volume rm sk-demo-vol && rm -rf /opt/sk-demo-bind /opt/backups

Feedback per E-Mail: feedback@serverkueche.de

Das könnte dir auch schmecken