Datenbank-Container im Produktivbetrieb - was man wissen muss

Datenbank-Container im Produktivbetrieb - was man wissen muss

Datenbanken in Docker zu betreiben ist absolut möglich — aber nur, wenn man ein paar wichtige Punkte beachtet.

Das wichtigste zuerst: Persistenz

Ohne Volume verliert ein Datenbankcontainer bei jedem Neustart alle Daten. Benannte Volumes sind der richtige Weg:

services:
  postgres:
    image: postgres:15
    volumes:
      - postgres-data:/var/lib/postgresql/data   # benanntes Volume

volumes:
  postgres-data:

Kein Bind-Mount für Datenbank-Daten — außer du weißt genau, was du tust. Bind-Mounts haben Berechtigungsprobleme und sind schwerer zu sichern.

Version pinnen

# Falsch — lädt irgendwann ein Breaking Update:
image: postgres:latest

# Richtig — kontrollierter Update-Prozess:
image: postgres:15.4

Datenbankversionen haben Migrationspfade. Ein unkontrolliertes Major-Update kann Daten beschädigen.

Port nicht nach außen exposen

Datenbanken gehören ins interne Netzwerk, nicht ins Internet:

services:
  postgres:
    image: postgres:15
    # KEIN ports: mapping!
    networks:
      - internal

  app:
    image: myapp
    networks:
      - internal
      - external

networks:
  internal:
    internal: true   # kein Zugang von außen
  external:

Ressourcen begrenzen

services:
  postgres:
    image: postgres:15
    deploy:
      resources:
        limits:
          memory: 2g
          cpus: "2.0"

Eine unkontrollierte Datenbank kann den gesamten Host-Speicher auffressen und andere Container killen.

Healthcheck

services:
  postgres:
    image: postgres:15
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

Mit Healthcheck weiß Docker, wann die Datenbank wirklich bereit ist. Abhängige Container warten mit depends_on: condition: service_healthy.

Nicht als root betreiben

PostgreSQL und MySQL-Images laufen standardmäßig als eigener User. Nicht überschreiben:

# Nicht tun:
user: root

Backup-Strategie

# PostgreSQL — Dump
docker exec postgres pg_dump -U postgres mydb > backup_$(date +%Y%m%d).sql

# MySQL — Dump
docker exec mysql mysqldump -u root -p$MYSQL_ROOT_PASSWORD mydb > backup_$(date +%Y%m%d).sql

# Volume-Backup (während Container läuft — für crash-consistent backup vorher stoppen)
docker run --rm \
  --volumes-from postgres \
  -v $(pwd)/backups:/backup \
  alpine tar czf /backup/postgres-data.tar.gz /var/lib/postgresql/data

Restore regelmäßig testen. Ein Backup das sich nicht restoren lässt, ist kein Backup.

PostgreSQL-Tuning über Umgebungsvariablen

environment:
  POSTGRES_USER: myuser
  POSTGRES_PASSWORD: securepassword
  POSTGRES_DB: mydb
  # Shared Buffers (empfohlen: 25% RAM)
  POSTGRES_SHARED_BUFFERS: 256MB

Für tieferes Tuning: postgresql.conf als Config-Volume einbinden.

Checkliste Produktion

  • [ ] Benanntes Volume für Daten
  • [ ] Fixe Image-Version (kein latest)
  • [ ] Kein Port nach außen
  • [ ] Memory-Limit gesetzt
  • [ ] Healthcheck konfiguriert
  • [ ] Backup-Job läuft und wird getestet
  • [ ] restart: unless-stopped

Zusammenfassung

Datenbanken in Docker sind produktionsreif — wenn Volume, Version, Netzwerk-Isolation, Ressourcen und Backup stimmen. Der häufigste Fehler: kein Backup-Test. Der zweit-häufigste: Port nach außen offen.