Berechtigungsprobleme mit Bind Mounts lösen - UID und GID verstehen

Berechtigungsprobleme mit Bind Mounts lösen - UID und GID verstehen

„Permission denied" beim Bind Mount ist einer der häufigsten Docker-Anfängerfehler – das Problem ist immer dasselbe: UID-Mismatch zwischen Container und Host.

Das Problem verstehen

Linux-Berechtigungen basieren auf numerischen User-IDs, nicht auf Namen. Wenn der Prozess im Container als UID 1000 läuft und das gemountete Verzeichnis auf dem Host root (UID 0) gehört, verweigert der Kernel den Zugriff.

Diagnose

# Welcher User läuft im Container?
docker exec mycontainer id
# uid=1000(appuser) gid=1000(appuser)

# Wem gehört das gemountete Verzeichnis?
docker exec mycontainer ls -lan /app/data
# drwxr-xr-x  2 root root 4096 Sep 1 12:00 data

Wenn UID und Besitzer nicht übereinstimmen, ist das die Ursache.

Auf dem Host nachsehen:

ls -lan /pfad/zum/host-verzeichnis

Lösung 1: Host-Verzeichnis dem richtigen User geben

Die simpelste Lösung: dem Host-Verzeichnis die UID zuweisen, die der Container-Prozess nutzt.

# Wenn Container-Prozess als UID 1000 läuft
chown -R 1000:1000 /host/pfad/zum/verzeichnis

# Oder rekursiv mit chmod kombinieren
chown -R 1000:1000 /host/pfad && chmod -R 755 /host/pfad

Lösung 2: Container als aktueller Host-User starten

Docker kann den Container als den aktuellen Host-User ausführen – damit stimmen UIDs automatisch überein:

docker run --user $(id -u):$(id -g) -v $(pwd)/data:/app/data myimage

In Compose:

services:
  app:
    image: myimage
    user: "${UID}:${GID}"
    volumes:
      - ./data:/app/data

Und in der .env Datei:

UID=1000
GID=1000

Achtung: Wenn der Container-Prozess bestimmte Dateien im Image als root besitzt (z.B. /var/run), kann das zu anderen Problemen führen.

Lösung 3: Dockerfile mit korrekter UID bauen

Für eigene Images die UID direkt im Dockerfile festlegen:

FROM node:20-alpine

# User mit passender UID anlegen
RUN addgroup -g 1001 appgroup && \
    adduser -u 1001 -G appgroup -s /bin/sh -D appuser

USER appuser
WORKDIR /app

Sonderfall: Root-owned Verzeichnisse

Manche Anwendungen erwarten root-Rechte für bestimmte Verzeichnisse beim Start, laufen dann aber als unprivilegierter User. Hier hilft ein Entrypoint-Skript:

#!/bin/sh
# Besitzer des gemounteten Verzeichnisses korrigieren
chown -R appuser:appuser /app/data
exec su-exec appuser "$@"

Sonderfall: NFS-Mounts

Bei NFS-Servern mit root_squash (Standard) werden root-Anfragen vom Container auf den anonymen User gemappt – das führt zu Berechtigungsfehlern. Lösung: entweder no_root_squash auf dem NFS-Server (Sicherheitsrisiko abwägen) oder den Container-Prozess als Non-Root mit der richtigen UID starten.

Sonderfall: SELinux

Auf RHEL/Fedora/CentOS mit aktivem SELinux schlägt der Zugriff auf Bind Mounts fehl, auch wenn UIDs stimmen. SELinux-Labels müssen gesetzt werden:

# :z = geteiltes Label (mehrere Container)
docker run -v $(pwd)/data:/app/data:z myimage

# :Z = privates Label (nur dieser Container)
docker run -v $(pwd)/data:/app/data:Z myimage

Schnell-Checkliste

# 1. Container-UID ermitteln
docker exec CONTAINER id

# 2. Host-Verzeichnis-Besitzer prüfen
ls -lan /host/pfad

# 3. Anpassen
chown UID:GID /host/pfad