services: db: image: postgres:17-alpine container_name: postgres_db_prod environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} volumes: - postgres_data:/var/lib/postgresql/data - ./be/init-db.sql:/docker-entrypoint-initdb.d/init-db.sql:ro networks: - app-network healthcheck: test: [ "CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}" ] interval: 30s timeout: 10s retries: 3 start_period: 30s restart: unless-stopped deploy: resources: limits: memory: 512M reservations: memory: 256M backend: container_name: fastapi_backend_prod build: context: ./be dockerfile: Dockerfile.prod target: production environment: - DATABASE_URL=${DATABASE_URL} - GEMINI_API_KEY=${GEMINI_API_KEY} - SECRET_KEY=${SECRET_KEY} - SESSION_SECRET_KEY=${SESSION_SECRET_KEY} - SENTRY_DSN=${SENTRY_DSN} - LOG_LEVEL=INFO - ENVIRONMENT=production - CORS_ORIGINS=${CORS_ORIGINS} - FRONTEND_URL=${FRONTEND_URL} networks: - app-network depends_on: db: condition: service_healthy restart: unless-stopped deploy: resources: limits: memory: 1G reservations: memory: 512M healthcheck: test: [ "CMD", "curl", "-f", "http://localhost:8000/health" ] interval: 30s timeout: 10s retries: 3 start_period: 30s frontend: container_name: frontend_prod build: context: ./fe dockerfile: Dockerfile.prod target: production args: - VITE_API_URL=${VITE_API_URL} - VITE_SENTRY_DSN=${VITE_SENTRY_DSN} ports: - "80:3000" networks: - app-network depends_on: - backend restart: unless-stopped deploy: resources: limits: memory: 256M reservations: memory: 128M redis: image: redis:7-alpine container_name: redis_prod command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD} volumes: - redis_data:/data networks: - app-network restart: unless-stopped deploy: resources: limits: memory: 256M reservations: memory: 128M volumes: postgres_data: driver: local redis_data: driver: local networks: app-network: driver: bridge