Docker Compose 2026: Multi-Container-Anwendungen, Netzwerke und DevOps-Interviewfragen

Docker Compose Tutorial für Multi-Container-Anwendungen mit Netzwerken, Volumes und Produktionsdeployment. Inklusive häufiger DevOps-Interviewfragen.

Docker Compose 2026: Multi-Container-Anwendungen, Netzwerke und DevOps-Interviewfragen

Docker Compose bleibt auch 2026 das bevorzugte Werkzeug für die Definition und Ausführung von Multi-Container-Docker-Anwendungen. Ob bei der Orchestrierung eines lokalen Entwicklungsstacks oder der Vorbereitung auf ein DevOps-Interview – das Verständnis von Compose-Netzwerken, Service-Abhängigkeiten und Produktionsmustern unterscheidet Junior-Entwickler von Senior-Praktikern.

Kernaussage

Docker Compose verwendet ein deklaratives YAML-Format, um Services, Netzwerke und Volumes in einer einzigen Datei zu definieren. Der Befehl docker compose up startet den gesamten Anwendungsstack mit isoliertem Netzwerk und persistentem Speicher.

Die Docker Compose Architektur verstehen

Docker Compose funktioniert nach einem einfachen Prinzip: Die Services der Anwendung werden in einer compose.yaml-Datei definiert (die moderne Namenskonvention ersetzt docker-compose.yml), und Compose übernimmt die Container-Erstellung, Netzwerkkonfiguration und Lifecycle-Verwaltung.

Die Docker Compose Spezifikation definiert drei Kernkonzepte:

  • Services: Container-Konfigurationen einschließlich Image, Build-Kontext, Umgebungsvariablen und Ressourcenlimits
  • Networks: Isolierte Kommunikationskanäle zwischen Services
  • Volumes: Persistenter Datenspeicher, der Container-Neustarts überlebt
yaml
# compose.yaml
services:
  api:
    build: ./api
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgres://db:5432/app
    depends_on:
      db:
        condition: service_healthy
    networks:
      - backend

  db:
    image: postgres:16
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=app
      - POSTGRES_PASSWORD_FILE=/run/secrets/db_password
    secrets:
      - db_password
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5
    networks:
      - backend

networks:
  backend:
    driver: bridge

volumes:
  postgres_data:

secrets:
  db_password:
    file: ./secrets/db_password.txt

Diese Konfiguration demonstriert mehrere produktionsreife Muster: Health Checks für die Abhängigkeitsreihenfolge, Docker Secrets für sensible Daten, benannte Volumes für Persistenz und explizite Netzwerkdefinitionen.

Docker Compose Netzwerke im Detail

Standardmäßig erstellt Compose ein einzelnes Netzwerk für die Anwendung. Alle Services treten diesem Netzwerk bei und können sich gegenseitig über den Servicenamen als Hostname erreichen. Das Verständnis dieses Netzwerkmodells ist grundlegend für eine spätere Kubernetes-Migration.

yaml
# compose.yaml
services:
  frontend:
    build: ./frontend
    ports:
      - "80:80"
    networks:
      - frontend-net
      - backend-net

  api:
    build: ./api
    networks:
      - backend-net

  cache:
    image: redis:7-alpine
    networks:
      - backend-net

  db:
    image: postgres:16
    networks:
      - backend-net

networks:
  frontend-net:
    driver: bridge
  backend-net:
    driver: bridge
    internal: true

Das Flag internal: true verhindert, dass das Backend-Netzwerk auf das externe Internet zugreifen kann. Der Frontend-Service verbindet beide Netzwerke und fungiert als einziger Einstiegspunkt. Diese Netzwerksegmentierung spiegelt Sicherheitspraktiken in Produktionsumgebungen wider.

DNS-Auflösung

Der eingebettete DNS-Server von Docker löst Servicenamen automatisch auf. Der api-Service erreicht die Datenbank unter db:5432 ohne manuelle IP-Konfiguration.

Multi-Stage Builds mit Compose

Produktions-Images sollten minimal sein. Multi-Stage Builds kombiniert mit Compose-Profilen ermöglichen unterschiedliche Konfigurationen für Entwicklung und Produktion.

dockerfile
# api/Dockerfile
# Stage 1: Build
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Stage 2: Production
FROM node:22-alpine AS production
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./
USER node
EXPOSE 3000
CMD ["node", "dist/index.js"]

# Stage 3: Development
FROM node:22-alpine AS development
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
USER node
CMD ["npm", "run", "dev"]
yaml
# compose.yaml
services:
  api:
    build:
      context: ./api
      target: ${BUILD_TARGET:-production}
    volumes:
      - ${API_VOLUMES:-./api/dist:/app/dist:ro}
    profiles:
      - ${COMPOSE_PROFILES:-prod}

Der Befehl BUILD_TARGET=development COMPOSE_PROFILES=dev docker compose up startet die Entwicklungskonfiguration mit Hot Reload.

Service-Abhängigkeiten und Health Checks

Die depends_on-Direktive steuert die Startreihenfolge, aber gestartete Container bedeuten nicht, dass Services bereit sind. Health Checks lösen dieses Timing-Problem – ein Muster, das häufig in DevOps-Interviews abgefragt wird.

yaml
# compose.yaml
services:
  api:
    build: ./api
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_started
      migrations:
        condition: service_completed_successfully

  migrations:
    build: ./api
    command: npm run migrate
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:16
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 3s
      retries: 5
      start_period: 10s

  cache:
    image: redis:7-alpine
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 3

Es existieren drei Abhängigkeitsbedingungen:

  • service_started: Standard, Container wurde gestartet
  • service_healthy: Health Check ist erfolgreich
  • service_completed_successfully: Container beendet mit Code 0 (für Init-Container)

Bereit für deine DevOps-Interviews?

Übe mit unseren interaktiven Simulatoren, Flashcards und technischen Tests.

Docker Compose für lokale Entwicklung

Entwicklungsumgebungen profitieren von Bind Mounts, Umgebungsüberschreibungen und Debugging-Tools. Die Datei compose.override.yaml wird automatisch mit compose.yaml zusammengeführt.

yaml
# compose.yaml (Basiskonfiguration)
services:
  api:
    build: ./api
    environment:
      - NODE_ENV=production

  db:
    image: postgres:16
yaml
# compose.override.yaml (Entwicklungsüberschreibungen)
services:
  api:
    build:
      target: development
    volumes:
      - ./api:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development
      - DEBUG=app:*
    ports:
      - "9229:9229"

  db:
    ports:
      - "5432:5432"

Das anonyme Volume /app/node_modules verhindert, dass die node_modules des Hosts die installierten Abhängigkeiten des Containers überschreiben.

Produktions-Deployment-Muster

Docker Compose eignet sich für Single-Host-Produktionsdeployments. Für Multi-Host-Orchestrierung bietet Kubernetes mit Helm bessere Skalierung, aber Compose bleibt für kleinere Anwendungen praktikabel.

yaml
# compose.prod.yaml
services:
  api:
    image: registry.example.com/api:${VERSION:-latest}
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: "0.5"
          memory: 512M
        reservations:
          cpus: "0.25"
          memory: 256M
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./certs:/etc/nginx/certs:ro
    depends_on:
      - api

Der deploy-Schlüssel konfiguriert Ressourcenlimits, Replikat-Anzahl und Neustartrichtlinien. Der Befehl docker compose -f compose.prod.yaml up -d startet den Produktionsstack im detached Modus.

Umgebungsvariablen und Secrets-Verwaltung

Sensible Konfiguration erfordert sorgfältige Handhabung. Docker Compose unterstützt mehrere Ansätze, von .env-Dateien bis zu Docker Secrets.

bash
# .env
POSTGRES_PASSWORD=dev_password_only
API_SECRET_KEY=local_dev_key
yaml
# compose.yaml
services:
  api:
    environment:
      - API_SECRET_KEY  # Erbt von Shell oder .env
      - DATABASE_URL=postgres://user:${POSTGRES_PASSWORD}@db:5432/app
    env_file:
      - ./config/api.env

Für die Produktion bieten Docker Secrets bessere Sicherheit, indem sensible Daten als Dateien statt als Umgebungsvariablen eingebunden werden:

yaml
# compose.prod.yaml
services:
  api:
    secrets:
      - api_key
      - db_password
    environment:
      - API_KEY_FILE=/run/secrets/api_key

secrets:
  api_key:
    external: true
  db_password:
    file: ./secrets/db_password.txt
Sicherheitshinweis

.env-Dateien mit Produktions-Secrets sollten niemals in die Versionskontrolle committed werden. Für Produktionsdeployments empfiehlt sich externes Secret-Management wie HashiCorp Vault oder Cloud-Provider-Lösungen.

Häufige DevOps-Interviewfragen zu Docker Compose

Interviewer testen das Verständnis von Compose-Konzepten durch praktische Szenarien. Diese Fragen erscheinen regelmäßig in DevOps- und Platform-Engineering-Interviews.

F: Wie kommunizieren Container in einem Compose-Netzwerk?

Docker erstellt für jedes Compose-Projekt ein dediziertes Bridge-Netzwerk. Services kommunizieren über ihre Servicenamen als Hostnamen. Der eingebettete DNS-Server löst diese Namen zu Container-IP-Adressen auf. Externer Traffic erreicht Services nur über explizit veröffentlichte Ports.

F: Was passiert, wenn docker compose up mit existierenden Containern ausgeführt wird?

Compose vergleicht die aktuelle Konfiguration mit laufenden Containern. Unveränderte Services laufen weiter. Modifizierte Services werden mit neuen Einstellungen neu erstellt. Neue Services werden frisch gestartet. Entfernte Services werden gestoppt und gelöscht.

F: Wie werden Datenbankmigrationen in Compose behandelt?

Zwei Muster existieren. Erstens: Verwendung eines Init-Containers mit service_completed_successfully-Abhängigkeit:

yaml
services:
  migrate:
    image: api:latest
    command: npm run migrate
    depends_on:
      db:
        condition: service_healthy

  api:
    depends_on:
      migrate:
        condition: service_completed_successfully

Zweitens: Migrationslogik im Anwendungs-Startskript einbinden, das ausstehende Migrationen prüft und anwendet, bevor Traffic akzeptiert wird.

F: Wie unterscheiden sich Volumes von Bind Mounts?

Benannte Volumes werden von Docker verwaltet, unter /var/lib/docker/volumes gespeichert und sind zwischen Hosts portabel. Bind Mounts bilden Host-Verzeichnisse direkt in Container ab, nützlich für die Entwicklung aber umgebungsabhängig. Volumes unterstützen Treiber für Remote-Speicher wie NFS oder Cloud-Block-Storage.

F: Was ist der Unterschied zwischen docker-compose und docker compose?

Das mit Bindestrich geschriebene docker-compose war das eigenständige, Python-basierte V1-Tool, das nun als veraltet gilt. Das mit Leerzeichen geschriebene docker compose ist die Go-basierte V2-Implementierung, die in die Docker CLI integriert ist. V2 ist schneller, unterstützt die Compose-Spezifikation vollständig und wird aktiv weiterentwickelt.

Debugging von Compose-Anwendungen

Die Fehlerbehebung bei containerisierten Anwendungen erfordert spezifische Techniken. Diese Befehle zeigen, was in einem Compose-Stack passiert:

bash
# Logs aller Services anzeigen
docker compose logs -f

# Logs eines bestimmten Services mit Zeitstempeln
docker compose logs -f --timestamps api

# Befehl in laufendem Container ausführen
docker compose exec api sh

# Einmaliger Befehl ausführen (startet neuen Container)
docker compose run --rm api npm test

# Ressourcennutzung anzeigen
docker compose top
docker stats

# Netzwerkkonfiguration inspizieren
docker network inspect project_backend

# Compose-Datei validieren
docker compose config

Der Befehl docker compose config führt alle Compose-Dateien zusammen und zeigt die endgültige Konfiguration – unverzichtbar für das Debugging von Variablen-Interpolationsproblemen.

Fazit

  • Docker Compose definiert Multi-Container-Anwendungen in einer einzigen YAML-Datei mit Services, Netzwerken und Volumes
  • Services kommunizieren via DNS über Servicenamen als Hostnamen innerhalb des Standard-Bridge-Netzwerks
  • Health Checks mit service_healthy-Bedingungen stellen die korrekte Startreihenfolge sicher
  • Die compose.override.yaml wird für entwicklungsspezifische Einstellungen wie Bind Mounts und Debug-Ports verwendet
  • Produktionsdeployments profitieren von Ressourcenlimits, Neustartrichtlinien und Docker Secrets für sensible Daten
  • Die docker compose CLI (V2) ersetzt das veraltete docker-compose (V1) mit besserer Performance und mehr Funktionen

Fang an zu üben!

Teste dein Wissen mit unseren Interview-Simulatoren und technischen Tests.

Teilen

Verwandte Artikel