# Backend development configuration # Usage: docker-compose up -d services: app: build: context: ./backend dockerfile: Dockerfile image: financial_agent_backend:dev container_name: financial_agent_backend ports: - "8001:8001" volumes: - ./backend/app:/app/app:ro - ./backend/skills:/app/skills:ro - ./backend/cli:/app/cli:ro - media_data:/app/media env_file: - ./backend/.env environment: - DEBUG=true - ENVIRONMENT=local - POSTGRES_HOST=db - REDIS_HOST=redis - CELERY_BROKER_URL=redis://redis:6379/0 - CELERY_RESULT_BACKEND=redis://redis:6379/0 # --ws websockets-sansio: uvicorn's `auto` picks the legacy websockets impl, # which is broken with websockets >=14 (handshake → HTTP 500). The sansio # implementation is the modern, compatible one. Required for the chat WS. command: uvicorn app.main:app --host 0.0.0.0 --port 8001 --reload --ws websockets-sansio networks: - backend depends_on: db: condition: service_healthy redis: condition: service_healthy restart: unless-stopped db: image: postgres:16-alpine container_name: financial_agent_db environment: - POSTGRES_USER=${POSTGRES_USER:-postgres} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-postgres} - POSTGRES_DB=${POSTGRES_DB:-financial_agent} volumes: - postgres_data:/var/lib/postgresql/data # Port exposed only for local development - remove in production ports: - "5432:5432" networks: - backend healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres}"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped redis: image: redis:7-alpine container_name: financial_agent_redis # Port exposed only for local development - remove in production ports: - "6379:6379" volumes: - redis_data:/data networks: - backend healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped celery_worker: image: financial_agent_backend:dev pull_policy: never container_name: financial_agent_celery_worker volumes: - ./backend/app:/app/app:ro - ./backend/skills:/app/skills:ro - media_data:/app/media command: celery -A app.worker.celery_app worker --loglevel=debug env_file: - ./backend/.env environment: - DEBUG=true - POSTGRES_HOST=db - REDIS_HOST=redis - CELERY_BROKER_URL=redis://redis:6379/0 - CELERY_RESULT_BACKEND=redis://redis:6379/0 networks: - backend depends_on: app: condition: service_started redis: condition: service_healthy db: condition: service_healthy restart: unless-stopped celery_beat: image: financial_agent_backend:dev pull_policy: never container_name: financial_agent_celery_beat volumes: - ./backend/app:/app/app:ro - ./backend/skills:/app/skills:ro command: celery -A app.worker.celery_app beat --loglevel=debug env_file: - ./backend/.env environment: - DEBUG=true - REDIS_HOST=redis - CELERY_BROKER_URL=redis://redis:6379/0 - CELERY_RESULT_BACKEND=redis://redis:6379/0 networks: - backend depends_on: app: condition: service_started redis: condition: service_healthy restart: unless-stopped flower: image: financial_agent_backend:dev pull_policy: never container_name: financial_agent_flower command: celery -A app.worker.celery_app flower --port=5555 ports: # Host 5556 (container stays 5555) so this stack coexists with medical_agent, # whose flower already owns host :5555. - "5556:5555" env_file: - ./backend/.env environment: - DEBUG=true - REDIS_HOST=redis - CELERY_BROKER_URL=redis://redis:6379/0 - CELERY_RESULT_BACKEND=redis://redis:6379/0 networks: - backend depends_on: app: condition: service_started redis: condition: service_healthy restart: unless-stopped networks: backend: driver: bridge volumes: media_data: postgres_data: redis_data: