Compose

Docker Compose ist ein Tool zur Definition und Ausführung von Multi-Container-Anwendungen. Es ist der Schlüssel für eine optimierte und effiziente Entwicklung und Bereitstellung.

Compose vereinfacht die Steuerung deines gesamten Application Stacks, indem es die Verwaltung von Diensten, Netzwerken und Volumes in einer einzigen, verständlichen YAML-Konfigurationsdatei erleichtert. Mit einem einzigen Befehl erstellst und startest du dann alle Dienste aus deiner Konfigurationsdatei.

Services

Services sind die zentralen Bausteine von Docker Compose. Jeder Service stellt eine containerisierte Anwendung oder Komponente dar.

services:
  service-name:
    # Konfiguration des Services

Images und Build

In einem Service kann der Container entweder von einem Image kommen oder aus einem Dockerfile gebildet werden.

Image
services:
  database:
    image: postgres:latest
Build
services:
  app:
    build:
      
        # Dockerfile name (optional if named 'Dockerfile')
      
        - NODE_ENV=production
        - VERSION=1.0.0
      

Konfiguration des Containers

Wir können den Container noch weiter konfigurieren.

Name
services:
  web:
    image: nginx
    
Restart Policy

Mit der Restart Policy legen wir fest, wann ein Container neugestartet werden soll.

  • no: Wird nie neugestartet

  • always: Container wird immer neugestartet, wenn er gestoppt wird

  • on-failure: Container wird nur neugestartet, wenn es einen Fehler gab

  • unless-stopped: Container wird immer neugestartet, ausser er wird manuell gestoppt

 services:
  app:
    image: nexus
    restart: unless-stopped

Port Mapping

Das Port Mapping kann entweder intern oder auch extern erfolgen.

Host
services:
  web:
    image: nginx
    ports:
      
Intern
services:
  api:
    image: nexus_api
    expose:
      

Umgebungsvariablen

Über Umgebungsvariablen können wir beispielsweise Variablen setzen.

services:
  app:
    image: nexus
    environment:
      - NODE_ENV=production
      - DEBUG=false
      - DATABASE_URL=postgresql://user:pass@db:5432/nexus

Abhängigkeiten

Mit dem Property depends_on können wir Abhängigkeiten zwischen den einzelnen Services definieren.

services:
  web:
    image: nginx
    depends_on:
      - api
      - db
  
  api:
    image: nexus_api
    depends_on:
      - db
  
  db:
    image: postgres

Health Checks

services:
  database:
    image: postgres
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
      
  api:
    image: myapi
    depends_on:
      db:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
      
  web:
    image: nginx
    depends_on:
      api:
        condition: service_healthy
      db:
        condition: service_started

Netzwerke

Netzwerke ermöglichen die Kommunikation zwischen Diensten und bieten Isolierung. Docker Compose erstellt automatisch ein Standardnetzwerk, aber du kannst benutzerdefinierte Netzwerke für eine bessere Kontrolle definieren.

Standardnetzwerk

Wenn du keine Netzwerke definierst, dann macht Docker Compose Folgendes:

  1. Erstellt ein Standard-Bridge-Netzwerk mit dem Namen {project_name}_default

  2. Verbindet alle Services zu diesem Netzwerk

  3. Services können mit ihren jeweiligen Servicenamen untereinander kommunizieren

Benutzerdefiniertes Netzwerk

Ohne Konfiguration
networks:
  nexus-network:

services:
  web:
    image: nginx
    networks:
      - nexus-network
  api:
    image: nexus_api
    networks:
      - nexus-network
Mit Konfiguration
networks:
  frontend:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 192.168.1.0/24
          gateway: 192.168.1.1
  
  backend:
    driver: bridge
    
    ipam:
      config:
        - subnet: 172.16.0.0/16

services:
  web:
    image: nginx
    networks:
      frontend:
        ipv4_address: 192.168.1.2
  
  api:
    image: nexus_backend
    networks:
      - frontend
      - backend
  
  database:
    image: postgres
    networks:
      - backend

Volumes

Volumes bieten persistenten Datenspeicher, der Neustarts und Entfernungen von Containern übersteht. Sie sind unverzichtbar für Datenbanken, Datei-Uploads, Protokolle und alle Daten, die erhalten bleiben müssen.

services:
  database:
    image: postgres
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

Secrets

Secrets bieten einen sicheren Speicher für sensible Daten wie Kennwörter, API-Schlüssel, Zertifikate und andere vertrauliche Informationen, die Container zur Laufzeit benötigen.

services:
  app:
    image: nexus
    environment:
      DB_PASSWORD_FILE: /run/secrets/db_password
      API_KEY_FILE: /run/secrets/api_key
      JWT_SECRET_FILE: /run/secrets/jwt_secret
    secrets:
      - db_password
      - api_key
      - jwt_secret

secrets:
  db_password:
    file: ./secrets/db_password.txt
  api_key:
    file: ./secrets/api_key.txt
  jwt_secret:
    file: ./secrets/jwt_secret.txt

Beispiel

services:
  mongodb:
    image: mongo:latest
    container_name: nexus_mongo
    restart: unless-stopped
    environment:
      MONGO_INITDB_ROOT_USERNAME_FILE: /run/secrets/mongo_root_username
      MONGO_INITDB_ROOT_PASSWORD_FILE: /run/secrets/mongo_root_password
      MONGO_INITDB_DATABASE: nexus
    secrets:
      - mongo_root_username
      - mongo_root_password
    volumes:
      - mongodb_data:/data/db
    networks:
      - nexus-network
    healthcheck:
      test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s

  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    container_name: nexus_backend
    restart: unless-stopped
    environment:
      - ASPNETCORE_ENVIRONMENT=Production
      - ASPNETCORE_URLS=http://+:8080
      - ConnectionStrings__MongoDB=mongodb://admin:${MONGO_ROOT_PASSWORD}@mongodb:27017/nexus?authSource=admin
      - JWT_SECRET_FILE=/run/secrets/jwt_secret
      - CORS_ORIGINS=http://localhost:3000,http://frontend:3000
    secrets:
      - jwt_secret
    ports:
      - "5000:8080"
    networks:
      - nexus-network
    depends_on:
      mongodb:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s
    volumes:
      - backend_logs:/app/logs

  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
      args:
        - NODE_ENV=production
        - REACT_APP_API_URL=http://localhost:5000
    container_name: nexus_frontend
    restart: unless-stopped
    environment:
      - NODE_ENV=production
    ports:
      - "3000:80"
    networks:
      - nexus-network
    depends_on:
      backend:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:80"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s

  nginx:
    image: nginx:alpine
    container_name: app_nginx
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/ssl:/etc/nginx/ssl:ro
    networks:
      - nexus-network
    depends_on:
      - frontend
      - backend
    healthcheck:
      test: ["CMD", "nginx", "-t"]
      interval: 30s
      timeout: 10s
      retries: 3

networks:
  nexus-network:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16

volumes:
  mongodb_data:
  backend_logs:

secrets:
  mongo_root_username:
    file: ./secrets/mongo_root_username.txt
  mongo_root_password:
    file: ./secrets/mongo_root_password.txt
  jwt_secret:
    file: ./secrets/jwt_secret.txt

Zuletzt aktualisiert

War das hilfreich?