Daten zwischen Containern teilen - Volumes und Netzwerk richtig einsetzen

Daten zwischen Containern teilen - Volumes und Netzwerk richtig einsetzen

Zwei Container müssen manchmal dieselben Daten nutzen – der richtige Ansatz hängt davon ab ob es um Dateien oder um Live-Kommunikation geht.

Zwei Arten des Teilens

Volumes – für Dateien, die von mehreren Containern gelesen oder geschrieben werden sollen (Uploads, Logs, Konfigs).

Netzwerk – für Live-Kommunikation zwischen Diensten (App → Datenbank, App → Cache).

Beide Konzepte nicht verwechseln: Eine Datenbank teilt man nicht über ein Volume, sondern über das Netzwerk.

Volumes zwischen Containern teilen

services:
  app:
    image: myapp
    volumes:
      - uploads:/app/uploads

  nginx:
    image: nginx:alpine
    volumes:
      - uploads:/var/www/uploads:ro  # Nginx liest nur

volumes:
  uploads:

Beide Container greifen auf dasselbe uploads-Volume zu. nginx mountet es read-only (:ro), weil es nur servieren, nicht schreiben soll.

Das Sidecar-Pattern

Ein Sidecar-Container ist ein Hilfscontainer der dasselbe Volume wie der Haupt-Container nutzt und eine unterstützende Aufgabe übernimmt:

services:
  app:
    image: myapp
    volumes:
      - logs:/app/logs

  log-shipper:
    image: fluent/fluent-bit
    volumes:
      - logs:/var/log/app:ro  # Liest Logs des App-Containers
    depends_on:
      - app

volumes:
  logs:
  • Weitere Sidecar-Beispiele:
  • App schreibt Dateien → Sidecar komprimiert und überträgt
  • App generiert Berichte → Sidecar sendet sie per E-Mail
  • App loggt → Sidecar leitet zu Loki weiter

Datenbanken niemals per Volume teilen

Datenbanken über ein geteiltes Volume anzubinden ist ein häufiger Fehler:

# FALSCH – nicht so machen
services:
  app1:
    volumes:
      - dbdata:/var/lib/mysql  # Beide schreiben gleichzeitig
  app2:
    volumes:
      - dbdata:/var/lib/mysql  # Datei-Locks, Corruption garantiert

Stattdessen: eine Datenbankinstanz, beide Apps verbinden sich über das Netzwerk:

services:
  db:
    image: mysql:8.0
    volumes:
      - dbdata:/var/lib/mysql

  app1:
    image: myapp1
    environment:
      DB_HOST: db

  app2:
    image: myapp2
    environment:
      DB_HOST: db

volumes:
  dbdata:

Read-only Volumes

Wenn ein Container Daten nur lesen, nicht schreiben darf:

services:
  worker:
    image: myworker
    volumes:
      - configs:/etc/myapp:ro  # Konfiguration schreibgeschützt
      - shared-data:/data:ro   # Daten nur lesen

Das :ro-Flag verhindert versehentliche Schreibzugriffe und macht die Intention explizit.

Volumes von einem anderen Container erben

volumes_from (veraltet, aber noch funktional) bindet alle Volumes eines anderen Containers ein:

services:
  data:
    image: alpine
    volumes:
      - myvolume:/data

  app:
    image: myapp
    volumes_from:
      - data  # Übernimmt alle Volumes von 'data'

Lieber explizit benannte Volumes nutzen – das ist klarer und weniger fehleranfällig als volumes_from.