version: '3.8' services: # PostgreSQL with TimescaleDB postgres: image: timescale/timescaledb:latest-pg15 container_name: pension_postgres environment: POSTGRES_USER: ${POSTGRES_USER:-pension_user} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-pension_password} POSTGRES_DB: ${POSTGRES_DB:-pension_quant} ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-pension_user} -d ${POSTGRES_DB:-pension_quant}"] interval: 10s timeout: 5s retries: 5 networks: - pension_network # Redis redis: image: redis:7-alpine container_name: pension_redis ports: - "6379:6379" volumes: - redis_data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 networks: - pension_network # Backend (FastAPI) backend: build: context: ./backend dockerfile: Dockerfile container_name: pension_backend environment: DATABASE_URL: postgresql://${POSTGRES_USER:-pension_user}:${POSTGRES_PASSWORD:-pension_password}@postgres:5432/${POSTGRES_DB:-pension_quant} REDIS_URL: redis://redis:6379/0 CELERY_BROKER_URL: redis://redis:6379/1 CELERY_RESULT_BACKEND: redis://redis:6379/2 SECRET_KEY: ${SECRET_KEY:-your-secret-key-change-in-production} ENVIRONMENT: ${ENVIRONMENT:-development} ports: - "8000:8000" volumes: - ./backend:/app depends_on: postgres: condition: service_healthy redis: condition: service_healthy command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload networks: - pension_network # Celery Worker celery_worker: build: context: ./backend dockerfile: Dockerfile container_name: pension_celery_worker environment: DATABASE_URL: postgresql://${POSTGRES_USER:-pension_user}:${POSTGRES_PASSWORD:-pension_password}@postgres:5432/${POSTGRES_DB:-pension_quant} REDIS_URL: redis://redis:6379/0 CELERY_BROKER_URL: redis://redis:6379/1 CELERY_RESULT_BACKEND: redis://redis:6379/2 SECRET_KEY: ${SECRET_KEY:-your-secret-key-change-in-production} ENVIRONMENT: ${ENVIRONMENT:-development} volumes: - ./backend:/app depends_on: postgres: condition: service_healthy redis: condition: service_healthy command: celery -A app.celery_worker worker --loglevel=info networks: - pension_network # Celery Beat (Scheduler) celery_beat: build: context: ./backend dockerfile: Dockerfile container_name: pension_celery_beat environment: DATABASE_URL: postgresql://${POSTGRES_USER:-pension_user}:${POSTGRES_PASSWORD:-pension_password}@postgres:5432/${POSTGRES_DB:-pension_quant} REDIS_URL: redis://redis:6379/0 CELERY_BROKER_URL: redis://redis:6379/1 CELERY_RESULT_BACKEND: redis://redis:6379/2 SECRET_KEY: ${SECRET_KEY:-your-secret-key-change-in-production} ENVIRONMENT: ${ENVIRONMENT:-development} volumes: - ./backend:/app depends_on: postgres: condition: service_healthy redis: condition: service_healthy command: celery -A app.celery_worker beat --loglevel=info networks: - pension_network # Flower (Celery Monitoring) flower: build: context: ./backend dockerfile: Dockerfile container_name: pension_flower environment: DATABASE_URL: postgresql://${POSTGRES_USER:-pension_user}:${POSTGRES_PASSWORD:-pension_password}@postgres:5432/${POSTGRES_DB:-pension_quant} CELERY_BROKER_URL: redis://redis:6379/1 CELERY_RESULT_BACKEND: redis://redis:6379/2 SECRET_KEY: ${SECRET_KEY:-your-secret-key-change-in-production} ENVIRONMENT: ${ENVIRONMENT:-development} ports: - "5555:5555" depends_on: - redis command: celery -A app.celery_worker flower --port=5555 networks: - pension_network # Frontend (React) frontend: build: context: ./frontend dockerfile: Dockerfile container_name: pension_frontend environment: VITE_API_URL: ${VITE_API_URL:-http://localhost:8000} ports: - "3000:3000" volumes: - ./frontend:/app - /app/node_modules command: npm start networks: - pension_network # Nginx (Reverse Proxy) nginx: image: nginx:alpine container_name: pension_nginx ports: - "80:80" volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro depends_on: - backend - frontend networks: - pension_network volumes: postgres_data: redis_data: networks: pension_network: driver: bridge