Home Up PDF Prof. Dr. Ingo Claßen
Docker Compose - ADBKT

Docker Compose

  • Tool zur Definition und Ausführung mehrerer Container als eine Anwendung
  • Konfiguration in einer einzigen Datei: docker-compose.yml (YAML-Format)
  • Orchestriert Services, Netzwerke und Volumes deklarativ
  • Ziel: reproduzierbare Entwicklungs- und Testumgebungen mit einem einzigen Befehl
  • Typische Anwendung: Web-App + Datenbank + Cache + Message Broker lokal starten

Grundprinzip

docker-compose.yml – Grundstruktur

Aufbau der Datei

  • services: ein Eintrag pro Container-Typ
  • networks: virtuelle Netzwerke (optional, Standard: bridge)
  • volumes: persistente Datenspeicher
  • configs / secrets: Konfiguration & Geheimnisse
  • Jeder Service entspricht einem Docker-Image
  • Compose erstellt alle Ressourcen im selben Projekt-Namespace
services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./html:/usr/share/nginx/html
    depends_on:
      - api

  api:
    build: ./api
    environment:
      - DB_URL=postgres://db/myapp
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:16
    environment:
      POSTGRES_DB: myapp
      POSTGRES_PASSWORD: secret
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready"]
      interval: 5s
      timeout: 3s
      retries: 5

volumes:
  pgdata:

networks:
  default:
    driver: bridge

Services: Images & Build

Fertiges Image verwenden

services:
  db:
    image: postgres:16-alpine
    # Registry: docker.io (Standard)
    # oder: ghcr.io/org/image:tag

  cache:
    image: redis:7-alpine

Image lokal bauen

services:
  api:
    build:
      context: ./api      # Verzeichnis
      dockerfile: Dockerfile
      args:
        - APP_ENV=production
      target: runtime     # Multi-Stage

Build + Image kombinieren

services:
  api:
    build: ./api          # kurze Form
    image: myorg/api:1.0  # Name für Push

  # Rebuild erzwingen:
  # docker compose build --no-cache
  # docker compose up --build

Wichtige Build-Befehle

  • docker compose build – alle Images bauen
  • docker compose pull – Images aktualisieren
  • docker compose push – Images in Registry pushen
  • --build-Flag bei up: Rebuild vor Start

Netzwerke

Standard-Netzwerk

  • Compose erstellt automatisch ein bridge-Netzwerk
  • Service-Name dient als DNS-Name innerhalb des Netzwerks
  • Container sehen sich gegenseitig per Namen: http://api:8000

Mehrere Netzwerke

services:
  nginx:
    networks:
      - frontend
      - backend
  api:
    networks:
      - backend
  db:
    networks:
      - backend

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true  # kein Internetzugang

Volumes

Volumes: Konfiguration

Named Volume

services:
  db:
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:
    driver: local
    # Daten bleiben bei 'down' erhalten
    # 'down -v' entfernt sie

Bind Mount

services:
  api:
    volumes:
      - ./src:/app/src        # Dev
      - ./config:/etc/config:ro  # readonly

tmpfs (RAM-Disk)

services:
  api:
    tmpfs:
      - /tmp
      - /run/secrets:size=1m

Volume-Befehle

  • docker volume ls – alle Volumes anzeigen
  • docker volume inspect pgdata – Details
  • docker compose down -v – Volumes löschen
  • docker volume prune – ungenutzte löschen

Externes Volume

volumes:
  pgdata:
    external: true  # vorher angelegt

Umgebungsvariablen & Secrets

Variablen definieren

services:
  api:
    environment:
      # direkt
      - APP_ENV=production
      # aus Shell-Umgebung
      - SECRET_KEY
      # als Map
      DB_HOST: db
      DB_PORT: 5432

.env-Datei (Standard)

# .env
DB_PASSWORD=geheim123
API_KEY=abc-xyz
IMAGE_TAG=1.2.0
services:
  api:
    image: myapp:${IMAGE_TAG}
    environment:
      - DB_PASSWORD=${DB_PASSWORD}

env_file

services:
  api:
    env_file:
      - .env.base
      - .env.local   # überschreibt

Secrets (Swarm-kompatibel)

services:
  api:
    secrets:
      - db_password

secrets:
  db_password:
    file: ./secrets/db_password.txt
    # oder: external: true
  • Secret wird als Datei in /run/secrets/ gemountet
  • .env niemals in Git committen → .gitignore
  • .env.example mit Platzhaltern bereitstellen

Port-Mapping & Expose

ports: Host ↔ Container

services:
  web:
    ports:
      # HOST:CONTAINER
      - "80:80"
      - "443:443"
      # nur localhost
      - "127.0.0.1:8080:80"
      # zufälliger Host-Port
      - "8000"
      # UDP
      - "5353:5353/udp"

expose: nur intern sichtbar

services:
  api:
    expose:
      - "8000"   # nur im Docker-Netz
      # kein Host-Port → sicherer

Port-Strategie

  • ports: Port wird am Host gebunden → von außen erreichbar
  • expose: nur für andere Services sichtbar, nicht am Host
  • Datenbank-Ports in Produktion nicht exponieren
  • Mehrere Ports eines Services können unterschiedlich behandelt werden

Sicherheitsempfehlung

Service Ansatz
nginx / Proxy ports: 80, 443
api, worker expose (intern)
db, redis expose / kein Port

depends_on & Healthchecks

depends_on-Bedingungen

services:
  api:
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started  # Standard
      migrations:
        condition: service_completed_successfully

Healthcheck definieren

  db:
    image: postgres:16
    healthcheck:
      test: ["CMD-SHELL",
             "pg_isready -U postgres"]
      interval: 5s
      timeout: 3s
      retries: 5
      start_period: 10s
  • service_started: Container läuft (default)
  • service_healthy: Healthcheck OK
  • service_completed_successfully: Exit-Code 0

Restart-Policies & Ressourcen

Restart-Policies

services:
  api:
    restart: unless-stopped
    # Optionen:
    # no         – kein Neustart (default)
    # always     – immer neu starten
    # on-failure – nur bei Fehler
    # unless-stopped – bis manuell gestoppt

Ressourcen begrenzen

  api:
    deploy:
      resources:
        limits:
          cpus: "0.50"
          memory: 512M
        reservations:
          cpus: "0.25"
          memory: 128M

Replicas (horizontale Skalierung)

  api:
    deploy:
      replicas: 3
      # docker compose up --scale api=3

Logging-Konfiguration

  api:
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"
    # Alternativen: syslog, journald,
    # fluentd, gelf, awslogs

Empfehlungen

  • Produktion: restart: unless-stopped
  • Entwicklung: restart: no (Fehler direkt sehen)
  • Ressourcenlimits schützen den Host vor Überlast