services: # PostgreSQL Database with PostGIS Extension # PostGIS is required for geo-service (OSM/Terrain features) postgres: image: postgis/postgis:16-3.4-alpine container_name: breakpilot-pwa-postgres ports: - "5432:5432" environment: POSTGRES_USER: breakpilot POSTGRES_PASSWORD: breakpilot123 POSTGRES_DB: breakpilot_db volumes: - breakpilot_pwa_data:/var/lib/postgresql/data - ./geo-service/scripts/init_postgis.sql:/docker-entrypoint-initdb.d/10-init-postgis.sql:ro healthcheck: test: ["CMD-SHELL", "pg_isready -U breakpilot -d breakpilot_db"] interval: 5s timeout: 5s retries: 5 networks: - breakpilot-pwa-network restart: unless-stopped # ============================================ # Valkey - Session Cache (Redis-Fork, BSD-3) # Redis-compatible, 100% Open Source # ============================================ valkey: image: valkey/valkey:8-alpine container_name: breakpilot-pwa-valkey ports: - "6379:6379" volumes: - valkey_data:/data command: valkey-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru healthcheck: test: ["CMD", "valkey-cli", "ping"] interval: 5s timeout: 3s retries: 5 networks: - breakpilot-pwa-network restart: unless-stopped # Go Consent Service consent-service: build: context: ./consent-service dockerfile: Dockerfile platform: linux/arm64 # Mac Mini Apple Silicon container_name: breakpilot-pwa-consent-service ports: - "8081:8081" environment: - DATABASE_URL=postgres://breakpilot:breakpilot123@postgres:5432/breakpilot_db?sslmode=disable - JWT_SECRET=${JWT_SECRET:-your-super-secret-jwt-key-change-in-production} - JWT_REFRESH_SECRET=${JWT_REFRESH_SECRET:-your-refresh-secret-key-change-in-production} - PORT=8081 - ENVIRONMENT=${ENVIRONMENT:-development} - ALLOWED_ORIGINS=http://localhost:8000,http://backend:8000 # Valkey Session Cache - VALKEY_URL=${VALKEY_URL:-redis://valkey:6379} - SESSION_TTL_HOURS=${SESSION_TTL_HOURS:-24} # E-Mail Konfiguration (Mailpit für Entwicklung) - SMTP_HOST=${SMTP_HOST:-mailpit} - SMTP_PORT=${SMTP_PORT:-1025} - SMTP_USERNAME=${SMTP_USERNAME:-} - SMTP_PASSWORD=${SMTP_PASSWORD:-} - SMTP_FROM_NAME=${SMTP_FROM_NAME:-BreakPilot} - SMTP_FROM_ADDR=${SMTP_FROM_ADDR:-noreply@breakpilot.app} - FRONTEND_URL=${FRONTEND_URL:-http://localhost:8000} depends_on: postgres: condition: service_healthy valkey: condition: service_healthy mailpit: condition: service_started networks: - breakpilot-pwa-network restart: unless-stopped # Python Backend backend: build: context: ./backend dockerfile: Dockerfile platform: linux/arm64 # Mac Mini Apple Silicon container_name: breakpilot-pwa-backend expose: - "8000" environment: - CONSENT_SERVICE_URL=http://consent-service:8081 - KLAUSUR_SERVICE_URL=http://klausur-service:8086 - TROCR_SERVICE_URL=${TROCR_SERVICE_URL:-http://host.docker.internal:18084} - CAMUNDA_URL=http://camunda:8080/engine-rest - DATABASE_URL=postgres://breakpilot:breakpilot123@postgres:5432/breakpilot_db?sslmode=disable - JWT_SECRET=${JWT_SECRET:-your-super-secret-jwt-key-change-in-production} - ENVIRONMENT=${ENVIRONMENT:-development} - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-} - DEBUG=${DEBUG:-false} # Alerts Agent (Google Alerts Monitoring) - ALERTS_AGENT_ENABLED=${ALERTS_AGENT_ENABLED:-true} # HashiCorp Vault - Secrets Management - VAULT_ADDR=${VAULT_ADDR:-http://vault:8200} - VAULT_TOKEN=${VAULT_TOKEN:-breakpilot-dev-token} - VAULT_SECRETS_PATH=${VAULT_SECRETS_PATH:-breakpilot} - USE_VAULT_SECRETS=${USE_VAULT_SECRETS:-true} # Keycloak Authentication (optional - wenn nicht gesetzt wird lokales JWT verwendet) - KEYCLOAK_SERVER_URL=${KEYCLOAK_SERVER_URL:-} - KEYCLOAK_REALM=${KEYCLOAK_REALM:-} - KEYCLOAK_CLIENT_ID=${KEYCLOAK_CLIENT_ID:-} - KEYCLOAK_CLIENT_SECRET=${KEYCLOAK_CLIENT_SECRET:-} - KEYCLOAK_VERIFY_SSL=${KEYCLOAK_VERIFY_SSL:-true} # Valkey Session Cache - VALKEY_URL=${VALKEY_URL:-redis://valkey:6379} - SESSION_TTL_HOURS=${SESSION_TTL_HOURS:-24} # vast.ai GPU Infrastructure - VAST_API_KEY=${VAST_API_KEY:-} - VAST_INSTANCE_ID=${VAST_INSTANCE_ID:-} - CONTROL_API_KEY=${CONTROL_API_KEY:-} - VAST_AUTO_SHUTDOWN=${VAST_AUTO_SHUTDOWN:-true} - VAST_AUTO_SHUTDOWN_MINUTES=${VAST_AUTO_SHUTDOWN_MINUTES:-30} # vLLM Backend - VLLM_BASE_URL=${VLLM_BASE_URL:-} - VLLM_ENABLED=${VLLM_ENABLED:-false} # Ollama Backend (lokal auf Mac Mini - DSGVO-konform) - OLLAMA_BASE_URL=${OLLAMA_BASE_URL:-http://host.docker.internal:11434} - OLLAMA_ENABLED=${OLLAMA_ENABLED:-true} - OLLAMA_DEFAULT_MODEL=${OLLAMA_DEFAULT_MODEL:-qwen2.5:14b} - OLLAMA_VISION_MODEL=${OLLAMA_VISION_MODEL:-qwen2.5vl:32b} - OLLAMA_CORRECTION_MODEL=${OLLAMA_CORRECTION_MODEL:-qwen2.5:14b} - OLLAMA_TIMEOUT=${OLLAMA_TIMEOUT:-180} # Breakpilot Drive Game API - GAME_USE_DATABASE=${GAME_USE_DATABASE:-true} - GAME_REQUIRE_AUTH=${GAME_REQUIRE_AUTH:-false} - GAME_REQUIRE_BILLING=${GAME_REQUIRE_BILLING:-false} - GAME_LLM_MODEL=${GAME_LLM_MODEL:-} # Compliance LLM Provider Configuration # Options: "anthropic" (cloud) or "self_hosted" (Ollama/local) - COMPLIANCE_LLM_PROVIDER=${COMPLIANCE_LLM_PROVIDER:-self_hosted} - SELF_HOSTED_LLM_URL=${SELF_HOSTED_LLM_URL:-http://host.docker.internal:11434} - SELF_HOSTED_LLM_MODEL=${SELF_HOSTED_LLM_MODEL:-llama3.1:70b} - COMPLIANCE_LLM_MAX_TOKENS=${COMPLIANCE_LLM_MAX_TOKENS:-4096} - COMPLIANCE_LLM_TEMPERATURE=${COMPLIANCE_LLM_TEMPERATURE:-0.3} - COMPLIANCE_LLM_TIMEOUT=${COMPLIANCE_LLM_TIMEOUT:-120} # E-Mail Konfiguration (Mailpit fuer Entwicklung) - SMTP_HOST=${SMTP_HOST:-mailpit} - SMTP_PORT=${SMTP_PORT:-1025} - SMTP_USERNAME=${SMTP_USERNAME:-} - SMTP_PASSWORD=${SMTP_PASSWORD:-} - SMTP_FROM_NAME=${SMTP_FROM_NAME:-BreakPilot} - SMTP_FROM_ADDR=${SMTP_FROM_ADDR:-noreply@breakpilot.app} extra_hosts: - "host.docker.internal:host-gateway" - "mac-mini:192.168.178.163" volumes: # Mount Docker socket for container monitoring (Mac Mini Control) - /var/run/docker.sock:/var/run/docker.sock:ro # Mount SBOM files for Security Dashboard - ./docs/sbom:/app/docs/sbom:ro # Mount Projekt-Verzeichnis fuer Test-Dashboard (echte Test-Discovery) - /Users/benjaminadmin/Projekte/breakpilot-pwa:/app/project:ro depends_on: - consent-service - valkey - mailpit networks: - breakpilot-pwa-network restart: unless-stopped # Mailpit - Lokaler E-Mail-Server für Entwicklung # Web UI: http://localhost:8025 # SMTP: localhost:1025 mailpit: image: axllent/mailpit:latest container_name: breakpilot-pwa-mailpit ports: - "8025:8025" # Web UI - "1025:1025" # SMTP Server environment: - MP_SMTP_AUTH_ACCEPT_ANY=true - MP_SMTP_AUTH_ALLOW_INSECURE=true networks: - breakpilot-pwa-network restart: unless-stopped # Go School Service (Klausuren, Noten, Zeugnisse) school-service: build: context: ./school-service dockerfile: Dockerfile platform: linux/arm64 # Mac Mini Apple Silicon container_name: breakpilot-pwa-school-service ports: - "8084:8084" environment: - DATABASE_URL=postgres://breakpilot:breakpilot123@postgres:5432/breakpilot_db?sslmode=disable - JWT_SECRET=${JWT_SECRET:-your-super-secret-jwt-key-change-in-production} - PORT=8084 - ENVIRONMENT=${ENVIRONMENT:-development} - ALLOWED_ORIGINS=http://localhost:8000,http://backend:8000 - LLM_GATEWAY_URL=http://backend:8000/llm depends_on: postgres: condition: service_healthy networks: - breakpilot-pwa-network restart: unless-stopped # Embedding Service (ML-heavy operations) # Handles: embeddings, re-ranking, PDF extraction # Separated for faster klausur-service builds embedding-service: build: context: ./klausur-service/embedding-service dockerfile: Dockerfile platform: linux/arm64 # Mac Mini Apple Silicon container_name: breakpilot-pwa-embedding-service ports: - "8087:8087" environment: - EMBEDDING_BACKEND=${EMBEDDING_BACKEND:-local} - LOCAL_EMBEDDING_MODEL=${LOCAL_EMBEDDING_MODEL:-BAAI/bge-m3} - LOCAL_RERANKER_MODEL=${LOCAL_RERANKER_MODEL:-BAAI/bge-reranker-v2-m3} - PDF_EXTRACTION_BACKEND=${PDF_EXTRACTION_BACKEND:-auto} - OPENAI_API_KEY=${OPENAI_API_KEY:-} - COHERE_API_KEY=${COHERE_API_KEY:-} - LOG_LEVEL=${LOG_LEVEL:-INFO} volumes: - embedding_models:/root/.cache/huggingface deploy: resources: limits: memory: 4G healthcheck: test: ["CMD", "python", "-c", "import httpx; httpx.get('http://localhost:8087/health').raise_for_status()"] interval: 30s timeout: 10s start_period: 120s retries: 3 networks: - breakpilot-pwa-network restart: unless-stopped # Klausur-Service (Abitur/Vorabitur Klausurkorrektur) # React + FastAPI Microservice # Web UI: http://localhost:8086 klausur-service: build: context: ./klausur-service dockerfile: Dockerfile platform: linux/arm64 # Native ARM64 - PaddlePaddle 3.3.0 unterstützt ARM64 container_name: breakpilot-pwa-klausur-service expose: - "8086" environment: - JWT_SECRET=${JWT_SECRET:-your-super-secret-jwt-key-change-in-production} - BACKEND_URL=http://backend:8000 - SCHOOL_SERVICE_URL=http://school-service:8084 - ENVIRONMENT=${ENVIRONMENT:-development} # PostgreSQL for OCR Labeling & Metrics - DATABASE_URL=postgres://breakpilot:breakpilot123@postgres:5432/breakpilot_db # Embedding Service (ML operations) - EMBEDDING_SERVICE_URL=http://embedding-service:8087 # BYOEH Configuration - QDRANT_URL=http://qdrant:6333 - BYOEH_ENCRYPTION_ENABLED=true - BYOEH_CHUNK_SIZE=1000 - BYOEH_CHUNK_OVERLAP=200 # MinIO Configuration (RAG Document Storage) - MINIO_ENDPOINT=minio:9000 - MINIO_ACCESS_KEY=${MINIO_ROOT_USER:-breakpilot} - MINIO_SECRET_KEY=${MINIO_ROOT_PASSWORD:-breakpilot123} - MINIO_BUCKET=breakpilot-rag - MINIO_SECURE=false # Ollama LLM Configuration - OLLAMA_BASE_URL=${OLLAMA_BASE_URL:-http://host.docker.internal:11434} - OLLAMA_ENABLED=${OLLAMA_ENABLED:-true} - OLLAMA_DEFAULT_MODEL=${OLLAMA_DEFAULT_MODEL:-qwen2.5:14b} - OLLAMA_VISION_MODEL=${OLLAMA_VISION_MODEL:-qwen2.5vl:32b} - OLLAMA_CORRECTION_MODEL=${OLLAMA_CORRECTION_MODEL:-qwen2.5:14b} # PaddleOCR Service (x86_64 via Rosetta) - PADDLEOCR_SERVICE_URL=http://paddleocr-service:8095 # HashiCorp Vault - Anthropic API Key for Loesung E - VAULT_ADDR=http://vault:8200 - VAULT_TOKEN=${VAULT_DEV_TOKEN:-breakpilot-dev-token} - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-} volumes: - klausur_uploads:/app/uploads - eh_uploads:/app/eh-uploads - ocr_labeling:/app/ocr-labeling - paddle_models:/root/.paddlex # Persist PaddleOCR models across restarts - ./docs:/app/docs # NIBIS Abitur-Dateien depends_on: - backend - school-service - embedding-service - postgres - qdrant - minio - paddleocr-service - vault networks: - breakpilot-pwa-network healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8086/health"] interval: 30s timeout: 30s retries: 3 start_period: 10s restart: unless-stopped # ============================================ # PaddleOCR Service - x86_64 via Rosetta # Runs in emulation to avoid ARM64 crashes # ============================================ paddleocr-service: build: context: ./paddleocr-service dockerfile: Dockerfile platform: linux/amd64 # Force x86_64 emulation via Rosetta container_name: breakpilot-pwa-paddleocr expose: - "8095" environment: - PADDLE_PDX_DISABLE_MODEL_SOURCE_CHECK=True volumes: - paddleocr_models:/root/.paddlex # Cache PaddleX models - paddleocr_models:/root/.paddleocr # Cache PaddleOCR 3.x models networks: - breakpilot-pwa-network healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8095/health"] interval: 30s timeout: 60s retries: 5 start_period: 180s # Models need time to load in emulation restart: unless-stopped # Qdrant Vector Database (BYOEH - Erwartungshorizont RAG) # REST API: http://localhost:6333 # gRPC: localhost:6334 qdrant: image: qdrant/qdrant:v1.12.1 container_name: breakpilot-pwa-qdrant ports: - "6333:6333" - "6334:6334" volumes: - qdrant_data:/qdrant/storage environment: - QDRANT__SERVICE__GRPC_PORT=6334 healthcheck: test: ["CMD-SHELL", "bash -c ' /dev/null 2>&1 || exit 1"] interval: 30s timeout: 10s start_period: 30s retries: 3 # DSMS Gateway - REST API für DSMS dsms-gateway: build: context: ./dsms-gateway dockerfile: Dockerfile container_name: breakpilot-pwa-dsms-gateway ports: - "8082:8082" environment: - IPFS_API_URL=http://dsms-node:5001 - IPFS_GATEWAY_URL=http://dsms-node:8080 - JWT_SECRET=${JWT_SECRET:-your-super-secret-jwt-key-change-in-production} depends_on: dsms-node: condition: service_healthy networks: - breakpilot-pwa-network restart: unless-stopped # ============================================ # Jitsi Meet - Videokonferenzen für Schulungen # Web UI: http://localhost:8443 # ============================================ # Jitsi Web Frontend jitsi-web: image: jitsi/web:stable-9823 container_name: breakpilot-pwa-jitsi-web expose: - "80" environment: - ENABLE_XMPP_WEBSOCKET=1 - ENABLE_COLIBRI_WEBSOCKET=1 - XMPP_DOMAIN=meet.jitsi - XMPP_BOSH_URL_BASE=http://jitsi-xmpp:5280 - XMPP_MUC_DOMAIN=muc.meet.jitsi - XMPP_GUEST_DOMAIN=guest.meet.jitsi - TZ=Europe/Berlin - PUBLIC_URL=${JITSI_PUBLIC_URL:-https://macmini} - JICOFO_AUTH_USER=focus - ENABLE_AUTH=${JITSI_ENABLE_AUTH:-0} - ENABLE_GUESTS=${JITSI_ENABLE_GUESTS:-1} - ENABLE_RECORDING=${JITSI_ENABLE_RECORDING:-1} - ENABLE_LIVESTREAMING=0 - DISABLE_HTTPS=1 # Branding - APP_NAME=BreakPilot Meet - NATIVE_APP_NAME=BreakPilot Meet - PROVIDER_NAME=BreakPilot volumes: - jitsi_web_config:/config - jitsi_web_crontabs:/var/spool/cron/crontabs - jitsi_transcripts:/usr/share/jitsi-meet/transcripts networks: breakpilot-pwa-network: aliases: - meet.jitsi restart: unless-stopped depends_on: - jitsi-xmpp # Prosody XMPP Server jitsi-xmpp: image: jitsi/prosody:stable-9823 container_name: breakpilot-pwa-jitsi-xmpp environment: - XMPP_DOMAIN=meet.jitsi - XMPP_AUTH_DOMAIN=auth.meet.jitsi - XMPP_MUC_DOMAIN=muc.meet.jitsi - XMPP_INTERNAL_MUC_DOMAIN=internal-muc.meet.jitsi - XMPP_GUEST_DOMAIN=guest.meet.jitsi - XMPP_RECORDER_DOMAIN=recorder.meet.jitsi - XMPP_CROSS_DOMAIN=true - TZ=Europe/Berlin - JICOFO_AUTH_USER=focus - JICOFO_AUTH_PASSWORD=${JITSI_JICOFO_AUTH_PASSWORD:-jicofo_secret_123} - JVB_AUTH_USER=jvb - JVB_AUTH_PASSWORD=${JITSI_JVB_AUTH_PASSWORD:-jvb_secret_123} - JIGASI_XMPP_USER=jigasi - JIGASI_XMPP_PASSWORD=${JITSI_JIGASI_XMPP_PASSWORD:-jigasi_secret_123} - JIBRI_XMPP_USER=jibri - JIBRI_XMPP_PASSWORD=${JITSI_JIBRI_XMPP_PASSWORD:-jibri_secret_123} - JIBRI_RECORDER_USER=recorder - JIBRI_RECORDER_PASSWORD=${JITSI_JIBRI_RECORDER_PASSWORD:-recorder_secret_123} - LOG_LEVEL=info - PUBLIC_URL=${JITSI_PUBLIC_URL:-https://macmini} - ENABLE_AUTH=${JITSI_ENABLE_AUTH:-0} - ENABLE_GUESTS=${JITSI_ENABLE_GUESTS:-1} volumes: - jitsi_prosody_config:/config - jitsi_prosody_plugins:/prosody-plugins-custom networks: breakpilot-pwa-network: aliases: - xmpp.meet.jitsi restart: unless-stopped # Jicofo - Jitsi Conference Focus jitsi-jicofo: image: jitsi/jicofo:stable-9823 container_name: breakpilot-pwa-jitsi-jicofo environment: - XMPP_DOMAIN=meet.jitsi - XMPP_AUTH_DOMAIN=auth.meet.jitsi - XMPP_MUC_DOMAIN=muc.meet.jitsi - XMPP_INTERNAL_MUC_DOMAIN=internal-muc.meet.jitsi - XMPP_SERVER=jitsi-xmpp - JICOFO_AUTH_USER=focus - JICOFO_AUTH_PASSWORD=${JITSI_JICOFO_AUTH_PASSWORD:-jicofo_secret_123} - TZ=Europe/Berlin - ENABLE_AUTH=${JITSI_ENABLE_AUTH:-0} - AUTH_TYPE=internal - ENABLE_AUTO_OWNER=${JITSI_ENABLE_AUTO_OWNER:-1} volumes: - jitsi_jicofo_config:/config networks: - breakpilot-pwa-network restart: unless-stopped depends_on: - jitsi-xmpp # JVB - Jitsi Videobridge (WebRTC SFU) jitsi-jvb: image: jitsi/jvb:stable-9823 container_name: breakpilot-pwa-jitsi-jvb ports: - "10000:10000/udp" # Video/Audio RTP - "8080:8080" # Colibri REST API (internal) environment: - XMPP_DOMAIN=meet.jitsi - XMPP_AUTH_DOMAIN=auth.meet.jitsi - XMPP_INTERNAL_MUC_DOMAIN=internal-muc.meet.jitsi - XMPP_SERVER=jitsi-xmpp - JVB_AUTH_USER=jvb - JVB_AUTH_PASSWORD=${JITSI_JVB_AUTH_PASSWORD:-jvb_secret_123} - JVB_PORT=10000 - JVB_STUN_SERVERS=meet-jit-si-turnrelay.jitsi.net:443 - TZ=Europe/Berlin - PUBLIC_URL=${JITSI_PUBLIC_URL:-https://macmini} - COLIBRI_REST_ENABLED=true - ENABLE_COLIBRI_WEBSOCKET=1 volumes: - jitsi_jvb_config:/config networks: - breakpilot-pwa-network restart: unless-stopped depends_on: - jitsi-xmpp # ============================================ # Jibri - Jitsi Recording Service # Recordings werden zu MinIO hochgeladen # ============================================ jibri: build: context: ./docker/jibri dockerfile: Dockerfile container_name: breakpilot-pwa-jibri environment: - XMPP_DOMAIN=meet.jitsi - XMPP_AUTH_DOMAIN=auth.meet.jitsi - XMPP_INTERNAL_MUC_DOMAIN=internal-muc.meet.jitsi - XMPP_RECORDER_DOMAIN=recorder.meet.jitsi - XMPP_SERVER=jitsi-xmpp - XMPP_MUC_DOMAIN=muc.meet.jitsi - JIBRI_XMPP_USER=jibri - JIBRI_XMPP_PASSWORD=${JITSI_JIBRI_XMPP_PASSWORD:-jibri_secret_123} - JIBRI_RECORDER_USER=recorder - JIBRI_RECORDER_PASSWORD=${JITSI_JIBRI_RECORDER_PASSWORD:-recorder_secret_123} - JIBRI_BREWERY_MUC=jibribrewery - JIBRI_RECORDING_DIR=/recordings - JIBRI_FINALIZE_SCRIPT=/config/finalize.sh - TZ=Europe/Berlin # X11 Display Konfiguration (Xvfb) - DISPLAY=:0 - RESOLUTION=1920x1080x24 # Optional: VNC fuer Debugging (Port 5900) # - VNC_PASSWORD=debug123 # MinIO Upload Konfiguration - MINIO_ENDPOINT=minio:9000 - MINIO_ACCESS_KEY=${MINIO_ROOT_USER} - MINIO_SECRET_KEY=${MINIO_ROOT_PASSWORD} - MINIO_BUCKET=breakpilot-recordings # Backend Webhook (wird nach Upload aufgerufen) - BACKEND_WEBHOOK_URL=http://backend:8000/api/recordings/webhook volumes: - jibri_recordings:/recordings - /dev/shm:/dev/shm shm_size: '2gb' cap_add: - SYS_ADMIN - NET_BIND_SERVICE networks: - breakpilot-pwa-network restart: unless-stopped depends_on: - jitsi-xmpp - minio profiles: - recording # ============================================ # Transcription Worker - Whisper + pyannote # Verarbeitet Recordings asynchron # ============================================ transcription-worker: build: context: ./backend dockerfile: Dockerfile.worker container_name: breakpilot-pwa-transcription-worker environment: - DATABASE_URL=postgres://breakpilot:breakpilot123@postgres:5432/breakpilot_db?sslmode=disable - REDIS_URL=redis://valkey:6379/1 - WHISPER_MODEL=${WHISPER_MODEL:-large-v3} - WHISPER_DEVICE=${WHISPER_DEVICE:-cpu} - WHISPER_COMPUTE_TYPE=${WHISPER_COMPUTE_TYPE:-int8} # pyannote.audio Token (HuggingFace) - PYANNOTE_AUTH_TOKEN=${PYANNOTE_AUTH_TOKEN:-} # MinIO Storage - MINIO_ENDPOINT=${MINIO_ENDPOINT:-minio:9000} - MINIO_ACCESS_KEY=${MINIO_ROOT_USER:-breakpilot} - MINIO_SECRET_KEY=${MINIO_ROOT_PASSWORD:-breakpilot123} - MINIO_BUCKET=breakpilot-recordings - MINIO_SECURE=false - TZ=Europe/Berlin volumes: - transcription_models:/root/.cache/huggingface - transcription_temp:/tmp/transcriptions deploy: resources: limits: memory: 8G reservations: memory: 4G networks: - breakpilot-pwa-network restart: unless-stopped depends_on: postgres: condition: service_healthy valkey: condition: service_healthy minio: condition: service_started profiles: - recording # ============================================ # Camunda 7 - BPMN Workflow Engine # Web UI: http://localhost:8089/camunda # REST API: http://localhost:8089/engine-rest # License: Apache 2.0 (kommerziell nutzbar) # ============================================ camunda: image: camunda/camunda-bpm-platform:7.21.0 container_name: breakpilot-pwa-camunda ports: - "8089:8080" environment: - DB_DRIVER=org.postgresql.Driver - DB_URL=jdbc:postgresql://postgres:5432/breakpilot_db - DB_USERNAME=breakpilot - DB_PASSWORD=${POSTGRES_PASSWORD:-breakpilot123} - DB_VALIDATE_ON_BORROW=true - WAIT_FOR=postgres:5432 - CAMUNDA_BPM_ADMIN_USER_ID=admin - CAMUNDA_BPM_ADMIN_USER_PASSWORD=${CAMUNDA_ADMIN_PASSWORD:-admin123} depends_on: postgres: condition: service_healthy networks: - breakpilot-pwa-network healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/camunda/api/engine || exit 1"] interval: 30s timeout: 10s retries: 5 start_period: 60s restart: unless-stopped profiles: - bpmn # ============================================ # GeoEdu Service - Self-Hosted OSM + Terrain # DSGVO-konforme Erdkunde-Lernplattform # Web UI: http://localhost:8088 # ============================================ geo-service: build: context: ./geo-service dockerfile: Dockerfile platform: linux/arm64 # Mac Mini Apple Silicon container_name: breakpilot-pwa-geo-service ports: - "8088:8088" environment: - PORT=8088 - ENVIRONMENT=${ENVIRONMENT:-development} - JWT_SECRET=${JWT_SECRET:-your-super-secret-jwt-key} # PostgreSQL (PostGIS fuer OSM-Daten) - DATABASE_URL=postgresql+asyncpg://breakpilot:breakpilot123@postgres:5432/breakpilot_db # MinIO (AOI Bundles, generierte Assets) - MINIO_ENDPOINT=minio:9000 - MINIO_ACCESS_KEY=${MINIO_ROOT_USER:-breakpilot} - MINIO_SECRET_KEY=${MINIO_ROOT_PASSWORD:-breakpilot123} - MINIO_BUCKET=breakpilot-geo - MINIO_SECURE=false # Ollama (Lernstationen generieren) - OLLAMA_BASE_URL=${OLLAMA_BASE_URL:-http://host.docker.internal:11434} - OLLAMA_MODEL=${OLLAMA_DEFAULT_MODEL:-qwen2.5:14b} # Tile Server Config - TILE_CACHE_DIR=/app/cache/tiles - DEM_CACHE_DIR=/app/cache/dem - MAX_AOI_SIZE_KM2=4 volumes: - geo_osm_data:/app/data/osm - geo_dem_data:/app/data/dem - geo_tile_cache:/app/cache/tiles - geo_aoi_bundles:/app/bundles extra_hosts: - "host.docker.internal:host-gateway" depends_on: postgres: condition: service_healthy minio: condition: service_started networks: - breakpilot-pwa-network healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8088/health"] interval: 30s timeout: 10s start_period: 60s retries: 3 restart: unless-stopped # ============================================ # Voice Service - PersonaPlex + TaskOrchestrator # Voice-First Interface fuer Breakpilot # DSGVO-konform: Keine Audio-Persistenz # Web UI: http://localhost:8091 # ============================================ voice-service: build: context: ./voice-service dockerfile: Dockerfile platform: linux/arm64 # Mac Mini Apple Silicon container_name: breakpilot-pwa-voice-service # Port 8091 wird von nginx HTTPS bereitgestellt (wss://macmini:8091) expose: - "8091" environment: - PORT=8091 - DATABASE_URL=postgresql+asyncpg://breakpilot:breakpilot123@postgres:5432/breakpilot_db - VALKEY_URL=redis://valkey:6379/2 - PERSONAPLEX_ENABLED=${PERSONAPLEX_ENABLED:-false} - PERSONAPLEX_WS_URL=${PERSONAPLEX_WS_URL:-ws://host.docker.internal:8998} - ORCHESTRATOR_ENABLED=true - FALLBACK_LLM_PROVIDER=${FALLBACK_LLM_PROVIDER:-ollama} - OLLAMA_BASE_URL=http://host.docker.internal:11434 - OLLAMA_VOICE_MODEL=qwen2.5:32b - BQAS_JUDGE_MODEL=qwen2.5:14b - KLAUSUR_SERVICE_URL=http://klausur-service:8086 - ENCRYPTION_ENABLED=true - AUDIO_PERSISTENCE=false - AUDIO_SAMPLE_RATE=24000 - ENVIRONMENT=${ENVIRONMENT:-development} - JWT_SECRET=${JWT_SECRET:-your-super-secret-jwt-key-change-in-production} volumes: - voice_session_data:/app/data/sessions extra_hosts: - "host.docker.internal:host-gateway" depends_on: postgres: condition: service_healthy valkey: condition: service_healthy networks: - breakpilot-pwa-network healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8091/health"] interval: 30s timeout: 10s start_period: 60s retries: 3 restart: unless-stopped # ============================================ # MkDocs Documentation # Web UI: http://localhost:8009 # Material Theme with German language support # ============================================ docs: build: context: . dockerfile: docs-src/Dockerfile platform: linux/arm64 # Mac Mini Apple Silicon container_name: breakpilot-pwa-docs ports: - "8009:80" networks: - breakpilot-pwa-network restart: unless-stopped healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:80/"] interval: 30s timeout: 10s retries: 3 volumes: breakpilot_pwa_data: # Embedding Service Model Cache embedding_models: # Valkey Session Cache valkey_data: dsms_data: klausur_uploads: eh_uploads: ocr_labeling: # PaddleOCR Model Cache (persist across container restarts) paddle_models: # PaddleOCR Service Model Cache (x86_64 emulation) paddleocr_models: qdrant_data: # Jitsi Volumes jitsi_web_config: jitsi_web_crontabs: jitsi_transcripts: jitsi_prosody_config: jitsi_prosody_plugins: jitsi_jicofo_config: jitsi_jvb_config: # Jibri Recording Volumes jibri_recordings: # Transcription Worker Volumes transcription_models: transcription_temp: # GeoEdu Service Volumes geo_osm_data: geo_dem_data: geo_tile_cache: geo_aoi_bundles: # Voice Service Volumes (transient sessions only) voice_session_data: networks: breakpilot-pwa-network: driver: bridge