services: postgres-db: image: timescale/timescaledb:2.15.2-pg16 container_name: fundamental-postgres command: -c shared_preload_libraries=timescaledb environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: fundamental volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres -d fundamental"] interval: 5s timeout: 5s retries: 10 networks: - app-network ports: - "5434:5432" nats: image: nats:2.9 volumes: - nats_data:/data networks: - app-network data-persistence-service: build: context: . dockerfile: docker/Dockerfile.dev container_name: data-persistence-service working_dir: /app/services/data-persistence-service command: ["cargo", "watch", "-x", "run --bin data-persistence-service-server"] environment: HOST: 0.0.0.0 PORT: 3000 # Rust service connects to the internal DB service name DATABASE_URL: postgresql://postgres:postgres@postgres-db:5432/fundamental RUST_LOG: info RUST_BACKTRACE: "1" depends_on: postgres-db: condition: service_healthy healthcheck: test: ["CMD-SHELL", "curl -fsS http://localhost:3000/health >/dev/null || exit 1"] interval: 5s timeout: 5s retries: 10 volumes: - ./:/app - cargo-target:/app/target - cargo-cache:/usr/local/cargo networks: - app-network frontend: build: context: . dockerfile: frontend/Dockerfile container_name: fundamental-frontend working_dir: /workspace/frontend command: ["/workspace/frontend/scripts/docker-dev-entrypoint.sh"] environment: # Vite Proxy Target VITE_API_TARGET: http://api-gateway:4000 # 让 Next 的 API 路由代理到新的 api-gateway NEXT_PUBLIC_BACKEND_URL: http://api-gateway:4000/v1 # SSR 内部访问自身 API 的内部地址,避免使用 x-forwarded-host 导致访问宿主机端口 FRONTEND_INTERNAL_URL: http://fundamental-frontend:3001 BACKEND_INTERNAL_URL: http://api-gateway:4000/v1 NODE_ENV: development NEXT_TELEMETRY_DISABLED: "1" volumes: - ./:/workspace # 隔离 node_modules,避免与宿主机冲突 - frontend_node_modules:/workspace/frontend/node_modules ports: - "13001:3001" depends_on: api-gateway: condition: service_healthy networks: - app-network api-gateway: build: context: . dockerfile: docker/Dockerfile.dev container_name: api-gateway restart: unless-stopped working_dir: /app/services/api-gateway command: ["cargo", "watch", "-x", "run --bin api-gateway"] ports: - "4000:4000" environment: SERVER_PORT: 4000 NATS_ADDR: nats://nats:4222 DATA_PERSISTENCE_SERVICE_URL: http://data-persistence-service:3000 REPORT_GENERATOR_SERVICE_URL: http://report-generator-service:8004 RUST_LOG: info,axum=info RUST_BACKTRACE: "1" depends_on: nats: condition: service_started data-persistence-service: condition: service_healthy alphavantage-provider-service: condition: service_started mock-provider-service: condition: service_started tushare-provider-service: condition: service_started finnhub-provider-service: condition: service_started yfinance-provider-service: condition: service_started report-generator-service: condition: service_started networks: - app-network healthcheck: test: ["CMD-SHELL", "curl -fsS http://localhost:4000/health >/dev/null || exit 1"] interval: 5s timeout: 5s retries: 12 volumes: - ./:/app - cargo-target:/app/target - cargo-cache:/usr/local/cargo mock-provider-service: build: context: . dockerfile: docker/Dockerfile.dev container_name: mock-provider-service working_dir: /app/services/mock-provider-service command: ["cargo", "watch", "-x", "run"] volumes: - workflow_data:/mnt/workflow_data - ./:/app - cargo-target:/app/target - cargo-cache:/usr/local/cargo environment: SERVER_PORT: 8006 NATS_ADDR: nats://nats:4222 DATA_PERSISTENCE_SERVICE_URL: http://data-persistence-service:3000 API_GATEWAY_URL: http://api-gateway:4000 WORKFLOW_DATA_PATH: /mnt/workflow_data SERVICE_HOST: mock-provider-service RUST_LOG: info,axum=info RUST_BACKTRACE: "1" depends_on: - nats - data-persistence-service networks: - app-network healthcheck: test: ["CMD-SHELL", "curl -fsS http://localhost:8006/health >/dev/null || exit 1"] interval: 5s timeout: 5s retries: 12 alphavantage-provider-service: build: context: . dockerfile: docker/Dockerfile.dev container_name: alphavantage-provider-service working_dir: /app/services/alphavantage-provider-service command: ["cargo", "watch", "-x", "run"] volumes: - workflow_data:/mnt/workflow_data - ./:/app - cargo-target:/app/target - cargo-cache:/usr/local/cargo environment: SERVER_PORT: 8000 NATS_ADDR: nats://nats:4222 DATA_PERSISTENCE_SERVICE_URL: http://data-persistence-service:3000 API_GATEWAY_URL: http://api-gateway:4000 WORKFLOW_DATA_PATH: /mnt/workflow_data SERVICE_HOST: alphavantage-provider-service RUST_LOG: info,axum=info RUST_BACKTRACE: "1" depends_on: - nats - data-persistence-service networks: - app-network healthcheck: test: ["CMD-SHELL", "curl -fsS http://localhost:8000/health >/dev/null || exit 1"] interval: 5s timeout: 5s retries: 12 tushare-provider-service: build: context: . dockerfile: docker/Dockerfile.dev container_name: tushare-provider-service working_dir: /app/services/tushare-provider-service command: ["cargo", "watch", "-x", "run"] volumes: - workflow_data:/mnt/workflow_data - ./:/app - cargo-target:/app/target - cargo-cache:/usr/local/cargo environment: SERVER_PORT: 8001 NATS_ADDR: nats://nats:4222 DATA_PERSISTENCE_SERVICE_URL: http://data-persistence-service:3000 TUSHARE_API_URL: http://api.waditu.com API_GATEWAY_URL: http://api-gateway:4000 WORKFLOW_DATA_PATH: /mnt/workflow_data SERVICE_HOST: tushare-provider-service RUST_LOG: info,axum=info RUST_BACKTRACE: "1" depends_on: - nats - data-persistence-service networks: - app-network healthcheck: test: ["CMD-SHELL", "curl -fsS http://localhost:8001/health >/dev/null || exit 1"] interval: 5s timeout: 5s retries: 12 finnhub-provider-service: build: context: . dockerfile: docker/Dockerfile.dev container_name: finnhub-provider-service working_dir: /app/services/finnhub-provider-service command: ["cargo", "watch", "-x", "run"] volumes: - workflow_data:/mnt/workflow_data - ./:/app - cargo-target:/app/target - cargo-cache:/usr/local/cargo environment: SERVER_PORT: 8002 NATS_ADDR: nats://nats:4222 DATA_PERSISTENCE_SERVICE_URL: http://data-persistence-service:3000 FINNHUB_API_URL: https://finnhub.io/api/v1 API_GATEWAY_URL: http://api-gateway:4000 WORKFLOW_DATA_PATH: /mnt/workflow_data SERVICE_HOST: finnhub-provider-service RUST_LOG: info,axum=info RUST_BACKTRACE: "1" depends_on: - nats - data-persistence-service networks: - app-network healthcheck: test: ["CMD-SHELL", "curl -fsS http://localhost:8002/health >/dev/null || exit 1"] interval: 5s timeout: 5s retries: 12 yfinance-provider-service: build: context: . dockerfile: docker/Dockerfile.dev container_name: yfinance-provider-service working_dir: /app/services/yfinance-provider-service command: ["cargo", "watch", "-x", "run"] volumes: - workflow_data:/mnt/workflow_data - ./:/app - cargo-target:/app/target - cargo-cache:/usr/local/cargo environment: SERVER_PORT: 8003 NATS_ADDR: nats://nats:4222 DATA_PERSISTENCE_SERVICE_URL: http://data-persistence-service:3000 API_GATEWAY_URL: http://api-gateway:4000 WORKFLOW_DATA_PATH: /mnt/workflow_data SERVICE_HOST: yfinance-provider-service RUST_LOG: info,axum=info RUST_BACKTRACE: "1" depends_on: - nats - data-persistence-service networks: - app-network dns: - 8.8.8.8 - 8.8.4.4 healthcheck: test: ["CMD-SHELL", "curl -fsS http://localhost:8003/health >/dev/null || exit 1"] interval: 5s timeout: 5s retries: 12 report-generator-service: build: context: . dockerfile: docker/Dockerfile.dev container_name: report-generator-service working_dir: /app/services/report-generator-service command: ["cargo", "watch", "-x", "run --bin report-generator-service"] volumes: - workflow_data:/mnt/workflow_data - ./:/app - cargo-target:/app/target - cargo-cache:/usr/local/cargo environment: SERVER_PORT: 8004 NATS_ADDR: nats://nats:4222 DATA_PERSISTENCE_SERVICE_URL: http://data-persistence-service:3000 GOTENBERG_URL: http://gotenberg:3000 WORKFLOW_DATA_PATH: /mnt/workflow_data RUST_LOG: info,axum=info RUST_BACKTRACE: "1" depends_on: - nats - data-persistence-service - gotenberg networks: - app-network healthcheck: test: ["CMD-SHELL", "curl -fsS http://localhost:8004/health >/dev/null || exit 1"] interval: 5s timeout: 5s retries: 12 gotenberg: image: gotenberg/gotenberg:8 container_name: gotenberg ports: - "3000:3000" networks: - app-network workflow-orchestrator-service: build: context: . dockerfile: docker/Dockerfile.dev container_name: workflow-orchestrator-service working_dir: /app/services/workflow-orchestrator-service command: ["cargo", "watch", "-x", "run --bin workflow-orchestrator-service"] volumes: - workflow_data:/mnt/workflow_data - ./:/app - cargo-target:/app/target - cargo-cache:/usr/local/cargo environment: SERVER_PORT: 8005 NATS_ADDR: nats://nats:4222 DATA_PERSISTENCE_SERVICE_URL: http://data-persistence-service:3000 WORKFLOW_DATA_PATH: /mnt/workflow_data RUST_LOG: info RUST_BACKTRACE: "1" depends_on: - nats - data-persistence-service networks: - app-network healthcheck: test: ["CMD-SHELL", "curl -fsS http://localhost:8005/health >/dev/null || exit 1"] interval: 5s timeout: 5s retries: 12 # ================================================================= # Python Services (Legacy - to be replaced) # ================================================================= volumes: workflow_data: pgdata: frontend_node_modules: nats_data: cargo-target: driver: local cargo-cache: driver: local networks: app-network: