# ================================================================ # UPDATED DOCKER COMPOSE - PROPER AUTHENTICATION ARCHITECTURE # ================================================================ networks: bakery-network: driver: bridge volumes: postgres_auth_data: postgres_training_data: postgres_forecasting_data: postgres_data_data: postgres_tenant_data: postgres_notification_data: redis_data: rabbitmq_data: prometheus_data: grafana_data: services: # ================================================================ # INFRASTRUCTURE SERVICES # ================================================================ # Redis - For caching, sessions, and rate limiting redis: image: redis:7-alpine container_name: bakery-redis command: redis-server --appendonly yes --requirepass redis_pass123 ports: - "6379:6379" volumes: - redis_data:/data networks: - bakery-network healthcheck: test: ["CMD", "redis-cli", "--raw", "incr", "ping"] interval: 30s timeout: 10s retries: 3 # RabbitMQ - Message broker rabbitmq: image: rabbitmq:3-management container_name: bakery-rabbitmq environment: - RABBITMQ_DEFAULT_USER=bakery - RABBITMQ_DEFAULT_PASS=forecast123 - RABBITMQ_DEFAULT_VHOST=/ ports: - "5672:5672" - "15672:15672" volumes: - rabbitmq_data:/var/lib/rabbitmq networks: - bakery-network healthcheck: test: ["CMD", "rabbitmq-diagnostics", "ping"] interval: 30s timeout: 10s retries: 3 # ================================================================ # DATABASE SERVICES # ================================================================ # Auth Database auth-db: image: postgres:15 container_name: bakery-auth-db environment: - POSTGRES_DB=auth_db - POSTGRES_USER=auth_user - POSTGRES_PASSWORD=auth_pass123 volumes: - postgres_auth_data:/var/lib/postgresql/data networks: - bakery-network healthcheck: test: ["CMD-SHELL", "pg_isready -U auth_user -d auth_db"] interval: 10s timeout: 5s retries: 5 # Tenant Database tenant-db: image: postgres:15 container_name: bakery-tenant-db environment: - POSTGRES_DB=tenant_db - POSTGRES_USER=tenant_user - POSTGRES_PASSWORD=tenant_pass123 volumes: - postgres_tenant_data:/var/lib/postgresql/data networks: - bakery-network healthcheck: test: ["CMD-SHELL", "pg_isready -U tenant_user -d tenant_db"] interval: 10s timeout: 5s retries: 5 # Training Database training-db: image: postgres:15 container_name: bakery-training-db environment: - POSTGRES_DB=training_db - POSTGRES_USER=training_user - POSTGRES_PASSWORD=training_pass123 volumes: - postgres_training_data:/var/lib/postgresql/data networks: - bakery-network healthcheck: test: ["CMD-SHELL", "pg_isready -U training_user -d training_db"] interval: 10s timeout: 5s retries: 5 # Forecasting Database forecasting-db: image: postgres:15 container_name: bakery-forecasting-db environment: - POSTGRES_DB=forecasting_db - POSTGRES_USER=forecasting_user - POSTGRES_PASSWORD=forecasting_pass123 volumes: - postgres_forecasting_data:/var/lib/postgresql/data networks: - bakery-network healthcheck: test: ["CMD-SHELL", "pg_isready -U forecasting_user -d forecasting_db"] interval: 10s timeout: 5s retries: 5 # Data Database data-db: image: postgres:15 container_name: bakery-data-db environment: - POSTGRES_DB=data_db - POSTGRES_USER=data_user - POSTGRES_PASSWORD=data_pass123 volumes: - postgres_data_data:/var/lib/postgresql/data networks: - bakery-network healthcheck: test: ["CMD-SHELL", "pg_isready -U data_user -d data_db"] interval: 10s timeout: 5s retries: 5 # Notification Database notification-db: image: postgres:15 container_name: bakery-notification-db environment: - POSTGRES_DB=notification_db - POSTGRES_USER=notification_user - POSTGRES_PASSWORD=notification_pass123 volumes: - postgres_notification_data:/var/lib/postgresql/data networks: - bakery-network healthcheck: test: ["CMD-SHELL", "pg_isready -U notification_user -d notification_db"] interval: 10s timeout: 5s retries: 5 # ================================================================ # MICROSERVICES # ================================================================ # API Gateway - Enhanced with Redis caching gateway: build: context: . dockerfile: ./gateway/Dockerfile container_name: bakery-gateway environment: # Service Discovery - AUTH_SERVICE_URL=http://auth-service:8000 - TENANT_SERVICE_URL=http://tenant-service:8000 - TRAINING_SERVICE_URL=http://training-service:8000 - FORECASTING_SERVICE_URL=http://forecasting-service:8000 - DATA_SERVICE_URL=http://data-service:8000 - NOTIFICATION_SERVICE_URL=http://notification-service:8000 # Authentication & Caching - JWT_SECRET_KEY=${JWT_SECRET_KEY:-your-super-secret-jwt-key-change-in-production} - JWT_ALGORITHM=HS256 - REDIS_URL=redis://:redis_pass123@redis:6379/0 # CORS Configuration - CORS_ORIGINS=http://localhost:3000,http://localhost:3001,https://panaderia.vercel.app # Service Configuration - SERVICE_NAME=gateway - SERVICE_VERSION=1.0.0 - LOG_LEVEL=INFO # Rate Limiting - RATE_LIMIT_CALLS_PER_MINUTE=60 - RATE_LIMIT_BURST=10 ports: - "8000:8000" depends_on: redis: condition: service_healthy rabbitmq: condition: service_healthy auth-service: condition: service_healthy tenant-service: condition: service_healthy networks: - bakery-network volumes: - ./gateway:/app - ./shared:/app/shared healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s timeout: 10s retries: 3 # Auth Service - Enhanced with proper JWT handling auth-service: build: context: . dockerfile: ./services/auth/Dockerfile container_name: bakery-auth-service environment: # Database - DATABASE_URL=postgresql+asyncpg://auth_user:auth_pass123@auth-db:5432/auth_db # Redis for sessions and rate limiting - REDIS_URL=redis://:redis_pass123@redis:6379/1 # Message Queue - RABBITMQ_URL=amqp://bakery:forecast123@rabbitmq:5672/ # JWT Configuration - JWT_SECRET_KEY=${JWT_SECRET_KEY:-your-super-secret-jwt-key-change-in-production} - JWT_ALGORITHM=HS256 - JWT_ACCESS_TOKEN_EXPIRE_MINUTES=30 - JWT_REFRESH_TOKEN_EXPIRE_DAYS=7 # Security Configuration - PASSWORD_MIN_LENGTH=8 - MAX_LOGIN_ATTEMPTS=5 - LOCKOUT_DURATION_MINUTES=30 # Service Configuration - SERVICE_NAME=auth-service - SERVICE_VERSION=1.0.0 - LOG_LEVEL=INFO ports: - "8001:8000" depends_on: auth-db: condition: service_healthy redis: condition: service_healthy rabbitmq: condition: service_healthy networks: - bakery-network volumes: - ./services/auth:/app - ./shared:/app/shared healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s timeout: 10s retries: 3 # Tenant Service - New enhanced service tenant-service: build: context: . dockerfile: ./services/tenant/Dockerfile container_name: bakery-tenant-service environment: # Database - DATABASE_URL=postgresql+asyncpg://tenant_user:tenant_pass123@tenant-db:5432/tenant_db # Redis for caching - REDIS_URL=redis://:redis_pass123@redis:6379/2 # Message Queue - RABBITMQ_URL=amqp://bakery:forecast123@rabbitmq:5672/ # Service Discovery - AUTH_SERVICE_URL=http://auth-service:8000 # JWT Configuration (for token verification) - JWT_SECRET_KEY=${JWT_SECRET_KEY:-your-super-secret-jwt-key-change-in-production} - JWT_ALGORITHM=HS256 # Service Configuration - SERVICE_NAME=tenant-service - SERVICE_VERSION=1.0.0 - LOG_LEVEL=INFO ports: - "8005:8000" depends_on: tenant-db: condition: service_healthy redis: condition: service_healthy rabbitmq: condition: service_healthy auth-service: condition: service_healthy networks: - bakery-network volumes: - ./services/tenant:/app - ./shared:/app/shared healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s timeout: 10s retries: 3 # Training Service - Enhanced with tenant isolation training-service: build: context: . dockerfile: ./services/training/Dockerfile container_name: bakery-training-service environment: # Database - DATABASE_URL=postgresql+asyncpg://training_user:training_pass123@training-db:5432/training_db # Redis for job queuing and caching - REDIS_URL=redis://:redis_pass123@redis:6379/3 # Message Queue - RABBITMQ_URL=amqp://bakery:forecast123@rabbitmq:5672/ # Service Discovery - AUTH_SERVICE_URL=http://auth-service:8000 - DATA_SERVICE_URL=http://data-service:8000 - TENANT_SERVICE_URL=http://tenant-service:8000 # JWT Configuration - JWT_SECRET_KEY=${JWT_SECRET_KEY:-your-super-secret-jwt-key-change-in-production} - JWT_ALGORITHM=HS256 # ML Configuration - MODEL_STORAGE_PATH=/app/models - MAX_TRAINING_TIME_MINUTES=30 - MIN_TRAINING_DATA_DAYS=30 - PROPHET_SEASONALITY_MODE=additive # Service Configuration - SERVICE_NAME=training-service - SERVICE_VERSION=1.0.0 - LOG_LEVEL=INFO ports: - "8002:8000" depends_on: training-db: condition: service_healthy redis: condition: service_healthy rabbitmq: condition: service_healthy auth-service: condition: service_healthy data-service: condition: service_healthy networks: - bakery-network volumes: - ./services/training:/app - ./shared:/app/shared - ./models:/app/models # Persistent model storage healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s timeout: 10s retries: 3 # Forecasting Service - Enhanced with proper auth forecasting-service: build: context: . dockerfile: ./services/forecasting/Dockerfile container_name: bakery-forecasting-service environment: # Database - DATABASE_URL=postgresql+asyncpg://forecasting_user:forecasting_pass123@forecasting-db:5432/forecasting_db # Redis for caching predictions - REDIS_URL=redis://:redis_pass123@redis:6379/4 # Message Queue - RABBITMQ_URL=amqp://bakery:forecast123@rabbitmq:5672/ # Service Discovery - AUTH_SERVICE_URL=http://auth-service:8000 - TRAINING_SERVICE_URL=http://training-service:8000 - DATA_SERVICE_URL=http://data-service:8000 # JWT Configuration - JWT_SECRET_KEY=${JWT_SECRET_KEY:-your-super-secret-jwt-key-change-in-production} - JWT_ALGORITHM=HS256 # ML Configuration - MODEL_STORAGE_PATH=/app/models - PREDICTION_CACHE_TTL_HOURS=6 # Service Configuration - SERVICE_NAME=forecasting-service - SERVICE_VERSION=1.0.0 - LOG_LEVEL=INFO ports: - "8003:8000" depends_on: forecasting-db: condition: service_healthy redis: condition: service_healthy rabbitmq: condition: service_healthy auth-service: condition: service_healthy training-service: condition: service_healthy networks: - bakery-network volumes: - ./services/forecasting:/app - ./shared:/app/shared - ./models:/app/models # Shared model storage healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s timeout: 10s retries: 3 # Data Service - Enhanced with external API integration data-service: build: context: . dockerfile: ./services/data/Dockerfile container_name: bakery-data-service environment: # Database - DATABASE_URL=postgresql+asyncpg://data_user:data_pass123@data-db:5432/data_db # Redis for API caching - REDIS_URL=redis://:redis_pass123@redis:6379/5 # Message Queue - RABBITMQ_URL=amqp://bakery:forecast123@rabbitmq:5672/ # Service Discovery - AUTH_SERVICE_URL=http://auth-service:8000 - TENANT_SERVICE_URL=http://tenant-service:8000 # External API Keys - AEMET_API_KEY=${AEMET_API_KEY:-eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1YWxmYXJvQGdtYWlsLmNvbSIsImp0aSI6ImRjZWVmNTEwLTdmYzEtNGMxNy1hODZkLWQ4NzdlZDc5ZDllNyIsImlzcyI6IkFFTUVUIiwiaWF0IjoxNzUyODMwMDg3LCJ1c2VySWQiOiJkY2VlZjUxMC03ZmMxLTRjMTctYTg2ZC1kODc3ZWQ3OWQ5ZTciLCJyb2xlIjoiIn0.C047gaiEhWhH4ItDgkHSwg8HzKTzw87TOPRTRf8j-2w} - MADRID_OPENDATA_API_KEY=${MADRID_OPENDATA_API_KEY:-your-madrid-opendata-key} # JWT Configuration - JWT_SECRET_KEY=${JWT_SECRET_KEY:-your-super-secret-jwt-key-change-in-production} - JWT_ALGORITHM=HS256 # Data Configuration - WEATHER_CACHE_TTL_HOURS=1 - TRAFFIC_CACHE_TTL_HOURS=1 - DATA_RETENTION_DAYS=365 # Service Configuration - SERVICE_NAME=data-service - SERVICE_VERSION=1.0.0 - LOG_LEVEL=INFO ports: - "8004:8000" depends_on: data-db: condition: service_healthy redis: condition: service_healthy rabbitmq: condition: service_healthy auth-service: condition: service_healthy networks: - bakery-network volumes: - ./services/data:/app - ./shared:/app/shared healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s timeout: 10s retries: 3 # Notification Service - Enhanced with WhatsApp and Email notification-service: build: context: . dockerfile: ./services/notification/Dockerfile container_name: bakery-notification-service environment: # Database - DATABASE_URL=postgresql+asyncpg://notification_user:notification_pass123@notification-db:5432/notification_db # Redis for queue management - REDIS_URL=redis://:redis_pass123@redis:6379/6 # Message Queue - RABBITMQ_URL=amqp://bakery:forecast123@rabbitmq:5672/ # Service Discovery - AUTH_SERVICE_URL=http://auth-service:8000 - TENANT_SERVICE_URL=http://tenant-service:8000 # Email Configuration - SMTP_HOST=${SMTP_HOST:-smtp.gmail.com} - SMTP_PORT=${SMTP_PORT:-587} - SMTP_USER=${SMTP_USER:-your-email@gmail.com} - SMTP_PASSWORD=${SMTP_PASSWORD:-your-app-password} - SMTP_FROM_NAME=Bakery Forecast # WhatsApp Configuration (Twilio) - WHATSAPP_ACCOUNT_SID=${WHATSAPP_ACCOUNT_SID:-your-twilio-sid} - WHATSAPP_AUTH_TOKEN=${WHATSAPP_AUTH_TOKEN:-your-twilio-token} - WHATSAPP_FROM_NUMBER=${WHATSAPP_FROM_NUMBER:-whatsapp:+14155238886} # JWT Configuration - JWT_SECRET_KEY=${JWT_SECRET_KEY:-your-super-secret-jwt-key-change-in-production} - JWT_ALGORITHM=HS256 # Service Configuration - SERVICE_NAME=notification-service - SERVICE_VERSION=1.0.0 - LOG_LEVEL=INFO ports: - "8006:8000" depends_on: notification-db: condition: service_healthy redis: condition: service_healthy rabbitmq: condition: service_healthy auth-service: condition: service_healthy networks: - bakery-network volumes: - ./services/notification:/app - ./shared:/app/shared healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s timeout: 10s retries: 3 # ================================================================ # MONITORING SERVICES # ================================================================ # Prometheus - Metrics collection prometheus: image: prom/prometheus:latest container_name: bakery-prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' - '--web.console.libraries=/etc/prometheus/console_libraries' - '--web.console.templates=/etc/prometheus/consoles' - '--storage.tsdb.retention.time=200h' - '--web.enable-lifecycle' ports: - "9090:9090" volumes: - ./infrastructure/monitoring/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml - prometheus_data:/prometheus networks: - bakery-network depends_on: - gateway - auth-service - tenant-service - training-service - forecasting-service - data-service - notification-service # Grafana - Metrics visualization grafana: image: grafana/grafana:latest container_name: bakery-grafana environment: - GF_SECURITY_ADMIN_PASSWORD=admin123 - GF_USERS_ALLOW_SIGN_UP=false ports: - "3002:3000" volumes: - grafana_data:/var/lib/grafana - ./infrastructure/monitoring/grafana/dashboards:/etc/grafana/provisioning/dashboards - ./infrastructure/monitoring/grafana/datasources:/etc/grafana/provisioning/datasources networks: - bakery-network depends_on: - prometheus # ================================================================ # FRONTEND SERVICES (Optional for development) # ================================================================ # React Dashboard dashboard: build: context: ./frontend dockerfile: Dockerfile.dev container_name: bakery-frontend environment: - REACT_APP_API_URL=http://localhost:8000/api/v1 - REACT_APP_WS_URL=ws://localhost:8000/ws ports: - "3000:3000" depends_on: - gateway networks: - bakery-network volumes: - ./frontend:/app - /app/node_modules command: npm start # ================================================================ # ENVIRONMENT VARIABLES TEMPLATE # ================================================================ # Create a .env file with these variables: # # # JWT Secret (CHANGE IN PRODUCTION!) # JWT_SECRET_KEY=your-super-secret-jwt-key-change-in-production-min-32-chars # # # External API Keys # AEMET_API_KEY=your-aemet-api-key-here # MADRID_OPENDATA_API_KEY=your-madrid-opendata-key-here # # # Email Configuration (Gmail example) # SMTP_HOST=smtp.gmail.com # SMTP_PORT=587 # SMTP_USER=your-email@gmail.com # SMTP_PASSWORD=your-app-specific-password # # # WhatsApp/Twilio Configuration # WHATSAPP_ACCOUNT_SID=your-twilio-account-sid # WHATSAPP_AUTH_TOKEN=your-twilio-auth-token # WHATSAPP_FROM_NUMBER=whatsapp:+14155238886