Daten nie im Container-Layer speichern - warum und wie

Daten nie im Container-Layer speichern - warum und wie

Wer Daten im Container-Layer statt in Volumes speichert, verliert sie beim nächsten docker compose up – ein Fehler der besonders bei Datenbanken schmerzt.

Was der Container-Layer ist

Jeder Container besteht aus Read-Only-Image-Layern plus einem beschreibbaren Container-Layer oben drauf. Alle Schreiboperationen landen dort. Wird der Container gelöscht (docker rm oder docker compose up mit geänderter Config), ist dieser Layer weg.

# Was hat der Container in seinen Layer geschrieben?
docker diff mycontainer

# Ausgabe:
# A /var/lib/mysql/ibdata1   ← Datenbank schreibt direkt in den Layer
# A /var/log/app/access.log  ← Logs landen im Container-Layer

A = Added, C = Changed, D = Deleted.

Der häufigste Fehler: Datenbank ohne Volume

# GEFÄHRLICH – Daten weg beim nächsten docker compose up
services:
  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: secret
    # Kein volumes:-Block = Daten im Container-Layer

Nach docker compose down && docker compose up ist die Datenbank leer.

# RICHTIG – Daten überleben Container-Neustarts
services:
  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: secret
    volumes:
      - dbdata:/var/lib/mysql

volumes:
  dbdata:

Was typisch im Container-Layer landet (und nicht sollte)

/var/lib/mysql/       → Named Volume
/var/lib/postgresql/  → Named Volume
/var/lib/redis/       → Named Volume
/var/www/html/uploads → Named Volume oder Bind Mount
/app/logs/            → Named Volume oder Bind Mount
/home/user/.config/   → Named Volume

Was im Container-Layer bleiben darf

Nicht alles muss persistiert werden. Gute Kandidaten für den Container-Layer:

/tmp/               → Temporäre Verarbeitung, nach Restart sowieso weg
/run/               → PID-Dateien, Sockets
Assets im Image     → CSS, JS, Templates – ins Image gebacken ist korrekt

Read-only Assets die sich mit dem Image ändern (z.B. HTML-Templates) gehören ins Image, nicht in ein Volume.

Mit docker diff prüfen

Bevor man ein Produktivsystem deployed:

# Container starten, Anwendung kurz nutzen
docker compose up -d
# Etwas Zeit lassen damit Daten geschrieben werden

# Prüfen was in den Container-Layer geschrieben wurde
docker diff myapp_db_1

Wenn hier Datenbankdateien oder Upload-Ordner auftauchen, fehlen Volumes.

Nachträgliche Volumes hinzufügen

Wenn ein laufender Container Daten im Layer hat und man ein Volume ergänzen will:

# 1. Daten aus dem Container-Layer exportieren
docker run --rm --volumes-from mycontainer -v $(pwd):/backup alpine \
  tar czf /backup/rescue.tar.gz /var/lib/mysql

# 2. Neues Volume mit diesen Daten befüllen
docker volume create rescued-data
docker run --rm -v rescued-data:/data -v $(pwd):/backup alpine \
  tar xzf /backup/rescue.tar.gz -C /data --strip-components=1

# 3. docker-compose.yml um Volume ergänzen und Container neu erstellen
docker compose up -d