SSD Nodes Learn Hosting plans →
Anleitungen Matt ConnorVon Matt Connor · Aktualisiert 2026-10-28

Docker Compose: Bind Mount oder Named Volume?

Erfahren Sie, wann Bind Mounts für Konfigurationen und Named Volumes für Daten sinnvoll sind, welche Rechtefehler auftreten und wie Sie Volumes prüfen, sichern und migrieren.

Bind mount oder Named Volume: die kurze Antwort

Docker-Compose-Volumes gibt es in zwei Varianten. Die Wahl hängt davon ab, wer die Dateien verwaltet. Verwenden Sie ein Bind Mount für Dateien, die Sie selbst schreiben und lesen, zum Beispiel Konfigurationen, Templates und statische Websites. Verwenden Sie ein Named Volume für Daten, die der Anwendung gehören, zum Beispiel Datenbankdateien, Suchindizes und hochgeladene Medien. Ein Bind Mount verweist auf einen Pfad auf dem Host, den Sie in einem Editor öffnen können. Ein Named Volume ist Speicher, den Docker für Sie erstellt und verwaltet. Sie greifen über Docker darauf zu.

Beide Varianten stehen unter demselben Schlüssel volumes: innerhalb eines Dienstes. Deshalb werden sie häufig verwechselt. Der Unterschied liegt in der linken Seite des Doppelpunkts. Beginnt die linke Seite mit . oder /, handelt es sich um einen Host-Pfad und damit um ein Bind Mount. Alles andere ist ein Name und damit ein Named Volume. Dieser Name muss zusätzlich im Block volumes: auf oberster Ebene deklariert werden.

Die beiden Syntaxvarianten in einer Compose-Datei

services:
  db:
    image: postgres:17
    environment:
      POSTGRES_PASSWORD: changeme
    volumes:
      - pgdata:/var/lib/postgresql/data
  web:
    image: nginx:1.27
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./site:/usr/share/nginx/html:ro

volumes:
  pgdata:

pgdata:/var/lib/postgresql/data ist ein benanntes Volume. ./nginx.conf:/etc/nginx/nginx.conf ist ein Bind-Mount, und :ro bindet es schreibgeschützt ein. Das ist der richtige Standard für Konfigurationsdateien, die ein Container niemals überschreiben sollte. Wenn der Eintrag volumes: auf oberster Ebene fehlt, bricht Compose mit service "db" refers to undefined volume pgdata ab.

Starten Sie die Umgebung und listen Sie auf, was Docker erstellt hat:

docker compose up -d
docker volume ls

Das Volume heißt nicht pgdata. Es heißt <project>_pgdata, wobei der Projektname standardmäßig dem Namen des Verzeichnisses entspricht, in dem die Compose-Datei liegt. Ein Verzeichnis namens myapp ergibt myapp_pgdata. Das ist wichtig, weil eine Umbenennung des Verzeichnisses ein neues, leeres Volume erzeugt. Die Anwendung sieht dann so aus, als hätte sie ihre Daten verloren. Das ist nicht der Fall: Das alte Volume wird weiterhin von docker volume ls aufgelistet. Legen Sie den Namen mit name: in der Compose-Datei fest oder setzen Sie COMPOSE_PROJECT_NAME, wenn das Verzeichnis verschoben werden könnte. Einstellungen dieser Art gehören zu Ihren übrigen Compose-Umgebungsdateien und Secrets.

Warum Berechtigungsfehler vor allem Bind-Mounts betreffen

Das ist der größte praktische Unterschied und geht hauptsächlich auf eine Regel zurück: Ein Named Volume, das bei der ersten Verwendung leer ist, wird aus dem Image befüllt, ein Bind-Mount dagegen nie.

Wenn Docker ein leeres Named Volume über ein Verzeichnis mountet, das im Image bereits Inhalte hat, kopiert Docker diese Inhalte mit den vom Image festgelegten Eigentümern und Modi in das Volume. Das offizielle Postgres-Image liefert /var/lib/postgresql/data aus, das seinem eigenen Benutzer postgres gehört. Daher gehört das Volume derselben numerischen ID, und die Datenbank startet.

Dieses Befüllen ist der einzige Vorsprung, den ein Named Volume erhält. Docker verwaltet den Speicherort des Volumes, aber Container lesen und schreiben dort mit normalen Dateisystemoperationen. Daher werden Eigentümer und Modi genauso durchgesetzt wie bei einem Bind-Mount. Ein Named Volume an einem Pfad, den das Image nicht besitzt, oder ein Volume, das zuerst von einem anderen Image oder Benutzer befüllt wurde, erhält keine Eigentümerinformationen aus dem Image. Auch dort kann einem Nicht-root-Prozess der Zugriff verweigert werden. Die folgende Prüfung mit id funktioniert für beide Arten.

Ein Bind-Mount verhält sich umgekehrt. Der Container sieht genau das, was auf dem Host vorhanden ist, einschließlich der Eigentümer. Die Inhalte des Images an diesem Pfad sind verborgen. Wenn das Host-Verzeichnis nicht vorhanden ist, erstellt der Docker-Daemon es. Der Daemon läuft als root, daher erhalten Sie ein Verzeichnis, das root:root gehört. Ein Container-Prozess, der als Nicht-root-Benutzer läuft, kann dann nicht hineinschreiben:

PermissionError: [Errno 13] Permission denied: '/data/app.db'

Die Lösung besteht darin, die Zahlen anzugleichen. Bei einem Bind-Mount werden Eigentümer anhand der numerischen Benutzer-ID verglichen, nicht anhand des Namens, weil der Container sein eigenes /etc/passwd hat. Ein Benutzer namens app im Container bedeutet auf dem Host nichts. Uid 1000 bedeutet auf beiden Seiten uid 1000, sofern der Daemon nicht User-Namespace-Remapping verwendet (userns-remap, festgelegt in /etc/docker/daemon.json oder in der dockerd-Befehlszeile). Beim Remapping wird jede Container-ID in einen untergeordneten Bereich auf dem Host verschoben. Im Beispielbereich von Docker, der bei 231072 beginnt, ist die Container-UID 0 die Host-UID 231072. Die Container-UID 1000 ist daher die Host-UID 232072.

id -u
mkdir -p ./data
docker compose exec web id
sudo chown -R 1000:1000 ./data

docker compose exec web id gibt die UID aus, unter der der Container-Prozess tatsächlich läuft. Ohne Remapping passen Sie das Host-Verzeichnis an diese Nummer an oder legen mit user: "1000:1000" im Dienst Ihre Nummer für den Container fest. Bei aktiviertem Remapping kann user: den Container nicht auf Ihre Host-Nummer festlegen, weil auch die von Ihnen gesetzte ID verschoben wird: user: "1000:1000" ergibt in diesem Beispielbereich weiterhin die Host-UID 232072. Ändern Sie stattdessen den Eigentümer des Host-Verzeichnisses auf die zugeordnete Host-ID (Ihr eigener Bereich steht in /etc/subuid und /etc/subgid). In der Docker-Dokumentation wird nur --userns=host auf docker container create, run oder exec als Möglichkeit genannt, das Remapping für einen einzelnen Container zu deaktivieren. user: festzulegen ist für eine selbst geschriebene Anwendung sauberer. Den Eigentümer des Host-Verzeichnisses zu ändern ist für ein Image, das Sie nicht selbst geschrieben haben, sicherer, weil manche Images einen Entrypoint als root starten, Berechtigungen abgeben und darunter bestimmte Eigentümer erwarten.

Zwei weitere Fallen sollten Sie kennen. Auf Fedora, RHEL und anderen Systemen, auf denen SELinux (security-enhanced Linux) im Enforcing-Modus läuft, wird ein Bind-Mount verweigert, bis er neu gekennzeichnet wurde. Fügen Sie daher :z für einen Pfad hinzu, der von mehreren Containern gemeinsam verwendet wird, oder :Z für einen Pfad, den nur ein Container verwenden soll, geschrieben als - ./data:/data:Z. Außerdem schlägt ein Bind-Mount einer einzelnen Datei statt eines Verzeichnisses fehl, wenn ein Editor die Datei ersetzt, anstatt sie direkt zu beschreiben, weil der Mount dem ursprünglichen Inode folgt. Der Container sieht dann weiterhin die alten Inhalte, bis Sie ihn neu starten. Mounten Sie das übergeordnete Verzeichnis, wenn die Datei häufig bearbeitet wird.

Leistung: Wo der Unterschied tatsächlich besteht

Auf einem Linux-Server durchlaufen beide Varianten denselben Kernel-Pfad. Der Durchsatzunterschied ist daher so gering, dass Sie die Auswahl nicht davon abhängig machen sollten. Named Volumes mit dem Standardtreiber local liegen wie der restliche Docker-Datenbestand im selben Dateisystem unter /var/lib/docker/volumes/. Ein Bind-Mount liegt dagegen an dem von Ihnen angegebenen Speicherort.

Der Unterschied zeigt sich bei Docker Desktop für macOS und Windows. Dort laufen Container innerhalb einer virtuellen Maschine. Ein Bind-Mount überträgt Daten vom Host-Dateisystem über eine Dateifreigabeschicht in diese virtuelle Maschine. Arbeitslasten mit vielen kleinen Dateioperationen, beispielsweise ein Node.js-Abhängigkeitsbaum oder ein Cache eines PHP-Frameworks, werden dadurch spürbar langsamer. Named Volumes bleiben innerhalb der virtuellen Maschine und verursachen diesen zusätzlichen Aufwand nicht. Deshalb binden viele Compose-Dateien für die Entwicklung das Quellverzeichnis ein, deklarieren aber für node_modules ein Named Volume.

Der andere tatsächliche Unterschied betrifft den Speicherort der Daten. Ein Bind-Mount nach /mnt/backup legt die Daten auf diesem Datenträger ab. Ein Named Volume wird auf dem Dateisystem gespeichert, das /var/lib/docker enthält. Auf einem VPS ist das normalerweise der Root-Datenträger. Eine Datenbank, die innerhalb eines Named Volumes wächst, füllt denselben Datenträger, auf dem auch Ihre System-Logs liegen. Prüfen Sie dies, bevor daraus ein Incident wird:

docker system df -v
df -h /var/lib/docker

docker system df -v listet alle Volumes mit ihrer Größe auf und markiert diejenigen, auf die kein Container mehr verweist.

Benanntes Volume untersuchen

Ein benanntes Volume ist keine Blackbox. Lassen Sie sich von Docker anzeigen, wo es liegt:

docker volume inspect myapp_pgdata

Das Feld Mountpoint enthält einen tatsächlichen Pfad auf dem Host, normalerweise /var/lib/docker/volumes/myapp_pgdata/_data. Sie können ihn mit sudo ls auslesen. Das ist für eine schnelle Prüfung nützlich. Behandeln Sie ihn nicht als Verzeichnis zum Bearbeiten von Dateien. Wenn Sie dort als root schreiben, tritt das oben beschriebene Problem mit den Besitzrechten erneut auf. Außerdem ist der Pfad ein Detail des local-Treibers, das andere Volume-Treiber nicht gemeinsam haben.

Die sichere Methode, den Inhalt anzusehen, ist ein kurzlebiger Container, der das Volume einbindet:

docker run --rm -v myapp_pgdata:/vol alpine ls -la /vol

Das funktioniert mit jedem Treiber, verwendet dieselben Berechtigungen wie der eigentliche Container und hinterlässt aufgrund von --rm nichts, was der kurzlebige Container selbst angelegt hat.

Jeden Typ sichern

Ein Bind-Mount ist ein gewöhnliches Verzeichnis. Jedes dateibasierte Backup-Tool kann es daher bereits sichern. Geben Sie den Host-Pfad als Quelle für das Backup an. Damit ist die Sicherung abgeschlossen. Für ein benanntes Volume ist ein zusätzlicher Schritt erforderlich, weil das Tool auf dessen Inhalt zugreifen muss. Binden Sie das Volume und ein Host-Verzeichnis in denselben kurzlebigen Container ein. Schreiben Sie anschließend ein Archiv:

docker run --rm \
  -v myapp_pgdata:/data:ro \
  -v "$PWD":/backup \
  alpine tar czf /backup/pgdata.tar.gz -C /data .

Stellen Sie die Daten wieder her, indem Sie sie in ein neues Volume zurückschreiben:

docker volume create myapp_pgdata_restored
docker run --rm \
  -v myapp_pgdata_restored:/data \
  -v "$PWD":/backup \
  alpine tar xzf /backup/pgdata.tar.gz -C /data

tar bewahrt die numerischen Eigentümer-IDs auf, wenn der Befehl als root im Container ausgeführt wird. Dadurch bleibt das wiederhergestellte Volume für die Anwendung verwendbar.

Für beide Typen gilt eine wichtige Warnung. Wenn Sie die Dateien einer laufenden Datenbank kopieren, enthält das Archiv einen sich während des Kopiervorgangs ändernden Datenbestand. Bei der Wiederherstellung kann dadurch ein beschädigter Zustand entstehen. Stoppen Sie den Dienst zuerst. Alternativ können Sie die Daten mit dem eigenen Tool der Datenbank exportieren, wie in docker compose exec -T db pg_dump -U postgres appdb > appdb.sql gezeigt. Dadurch entsteht eine einfache Datei, die Sie anschließend zusammen mit Ihren Compose-Dateien in eine normale verschlüsselte restic-Backup-Routine aufnehmen können.

Bind-Mount zu einem benannten Volume migrieren

Der Vorgang ist ein Kopieren, kein Umbenennen, und dauert etwa eine Minute.

docker compose down
docker volume create myapp_pgdata
docker run --rm \
  -v "$PWD/data":/from \
  -v myapp_pgdata:/to \
  alpine sh -c 'cp -a /from/. /to/'

cp -a behält Eigentümer, Berechtigungen und Zeitstempel bei. Der Container-Benutzer, der das alte Verzeichnis lesen konnte, kann daher auch das neue Volume lesen. Ändern Sie anschließend den Dienst so, dass er pgdata:/var/lib/postgresql/data verwendet, fügen Sie pgdata zum übergeordneten volumes:-Block hinzu, führen Sie docker compose up -d aus und prüfen Sie die Anwendungslogs, bevor Sie das alte Verzeichnis löschen. In die andere Richtung verwenden Sie denselben Befehl, wobei /from und /to vertauscht werden.

Beachten Sie beim Testen einen Punkt. docker compose down lässt benannte Volumes unverändert. docker compose down -v löscht dagegen jedes benannte Volume, das im Projekt deklariert ist. Dieser Vorgang kann nicht rückgängig gemacht werden. Ein Bind-Mount bleibt in beiden Fällen erhalten, weil Docker dieses Verzeichnis nie verwaltet hat. Wenn die Lifecycle-Befehle für Sie noch neu sind, erklärt der Grundlagenleitfaden zu Docker Compose für einen VPS deren Verwendung.

Auswahl für jeden Dienst

Fragen Sie, welcher Prozess die Datei schreibt. Konfiguration, die Sie in einem Texteditor bearbeiten und in git committen, gehört in einen Bind-Mount, der unter :ro eingehängt wird. So bleibt sie sichtbar und wird versioniert. Anwendungsdaten, die Sie nie manuell öffnen, gehören in ein benanntes Volume. Docker übernimmt dann die Berechtigungen aus dem Image, und die Daten hängen nicht von einem Hostpfad ab.

Der Mischfall sind Mediendateien. Eine Fotobibliothek wird von der Anwendung geschrieben, aber auch von Ihnen verwaltet. Außerdem ist sie häufig groß genug, um dafür einen bestimmten Datenträger verwenden zu wollen. Binden Sie sie in einen Pfad auf diesem Datenträger ein, und legen Sie den Eigentümer einmal bewusst fest. Nach diesem Muster werden die meisten Self-Hosting-Stacks aufgebaut: benannte Volumes für Datenbanken und Caches, Bind-Mounts für die Konfiguration und für das große Verzeichnis, das Ihnen wichtig ist. Ein Supportdesk wie Chatwoot auf einem VPS entspricht genau diesem Muster: PostgreSQL liegt in einem benannten Volume, und die hochgeladenen Anhänge liegen in einem Pfad, auf den Sie ein Backup ansetzen können.

FAQ

Was ist der Unterschied zwischen einem Bind-Mount und einem Named Volume?

Ein Bind-Mount bildet einen Pfad auf dem Host in den Container ab. Beide Seiten sehen dasselbe Verzeichnis, und Sie können es mit normalen Werkzeugen bearbeiten. Ein Named Volume ist ein Speicherbereich, den Docker erstellt und verwaltet. Es wird über seinen Namen referenziert und im volumes:-Block der obersten Ebene deklariert. Der praktische Unterschied betrifft die Eigentümerschaft: Bind-Mounts eignen sich für Konfigurationen, die Sie verwalten, Named Volumes für Daten, die die Anwendung verwaltet.

Warum erhalte ich bei einem Bind-Mount "permission denied", aber nicht bei einem Named Volume?

Ein leeres Named Volume wird aus dem Image befüllt. Daher übernimmt es normalerweise die vom Image festgelegte Eigentümerschaft, und der Container-Benutzer kann darin schreiben. Berechtigungen werden weiterhin durchgesetzt. Der Vorgang kann also genauso fehlschlagen, wenn das Image an diesem Pfad keine Inhalte besitzt. Ein Bind-Mount zeigt das Host-Verzeichnis exakt so, wie es vorhanden ist. Wenn Docker das Verzeichnis erstellen musste, gehört es root. Führen Sie docker compose exec <service> id aus, um die numerische ID des Containers anzuzeigen, und ändern Sie anschließend mit sudo chown -R <uid>:<gid> den Eigentümer des Host-Verzeichnisses. Wenn der Daemon keine User-Namespaces umsetzt, können Sie alternativ user: "1000:1000" im Dienst festlegen. Verwendet der Daemon User-Namespace-Umsetzung, ändern Sie den Eigentümer stattdessen auf die umgesetzte Host-ID, weil die Container-IDs auf dem Host verschoben sind und user: daran nichts ändert.

Wo speichert Docker Named Volumes auf der Festplatte?

Mit dem standardmäßigen local-Treiber liegen sie unter /var/lib/docker/volumes/<volume>/_data. docker volume inspect <volume> gibt den genauen Mountpoint aus. Lesen Sie diesen Pfad, wenn Sie etwas prüfen müssen, aber schreiben Sie nur über einen Container dorthin. Wenn Sie als root auf dem Host Änderungen vornehmen, kann sich die Eigentümerschaft so ändern, dass der Container sie nicht mehr erwartet.

Wie sichere ich ein Named Volume?

Starten Sie einen kurzlebigen Container, in dem sowohl das Volume als auch ein Host-Verzeichnis gemountet sind. Archivieren Sie die Daten dann mit docker run --rm -v myvol:/data:ro -v "$PWD":/backup alpine tar czf /backup/myvol.tar.gz -C /data . vom einen in das andere. Bei einer Datenbank sollten Sie mit dem eigenen Werkzeug der Datenbank einen Dump erstellen, statt laufende Dateien zu kopieren. Eine Dateikopie während laufender Schreibvorgänge kann sonst in einem beschädigten Zustand wiederhergestellt werden.

Löscht docker compose down meine Volumes?

docker compose down entfernt Container und Netzwerke und lässt Named Volumes bestehen. docker compose down -v löscht zusätzlich jedes Named Volume, das das Projekt deklariert, dauerhaft. Bind-Mounts werden von keinem der beiden Befehle entfernt, weil das Verzeichnis dem Host und nicht Docker gehört.

War dieser Artikel hilfreich?