services: ib-gateway: image: ghcr.io/gnzsnz/ib-gateway:stable restart: always env_file: - ${COMPOSE_APP_ENV_FILE:-docker.env} environment: - TRADING_MODE=${TRADING_MODE:-paper} - READ_ONLY_API=${READ_ONLY_API:-no} - TWOFA_TIMEOUT_ACTION=${TWOFA_TIMEOUT_ACTION:-restart} - AUTO_RESTART_TIME=${AUTO_RESTART_TIME:-11:59 PM} - RELOGIN_AFTER_TWOFA_TIMEOUT=${RELOGIN_AFTER_TWOFA_TIMEOUT:-yes} - EXISTING_SESSION_DETECTED_ACTION=${EXISTING_SESSION_DETECTED_ACTION:-primaryoverride} - TIME_ZONE=${TIME_ZONE:-America/New_York} ports: - "127.0.0.1:4001:4003" - "127.0.0.1:4002:4004" - "127.0.0.1:5900:5900" volumes: - ./secrets:/run/secrets:ro healthcheck: test: ["CMD-SHELL", "bash -lc ': >/dev/tcp/127.0.0.1/4004' || bash -lc ': >/dev/tcp/127.0.0.1/4003' || exit 1"] interval: 30s timeout: 10s retries: 5 start_period: 90s networks: - ibkr-net ibkr-dashboard: build: . restart: unless-stopped env_file: - ${COMPOSE_APP_ENV_FILE:-docker.env} environment: - IBKR_HOST=ib-gateway - IBKR_PORT=4004 - DB_PATH=/app/data/trades.db # Port exposed only for local testing — can be removed when accessed exclusively via Traefik ports: - "127.0.0.1:8000:8000" volumes: - ./data:/app/data - ./secrets:/run/secrets:ro depends_on: ib-gateway: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s timeout: 10s retries: 3 start_period: 15s labels: - "traefik.enable=true" - "traefik.docker.network=${TRAEFIK_NETWORK:-traefik-public}" # Router - "traefik.http.routers.ibkr-dashboard.rule=Host(`${TRAEFIK_HOST:-ibkr.local}`)" - "traefik.http.routers.ibkr-dashboard.entrypoints=${TRAEFIK_ENTRYPOINT:-websecure}" - "traefik.http.routers.ibkr-dashboard.tls=true" - "traefik.http.routers.ibkr-dashboard.middlewares=ibkr-sse-headers@docker" # Service — port 8000 with immediate SSE flush - "traefik.http.services.ibkr-dashboard.loadbalancer.server.port=8000" - "traefik.http.services.ibkr-dashboard.loadbalancer.responseforwarding.flushinterval=-1" - "traefik.http.services.ibkr-dashboard.loadbalancer.healthcheck.path=/health" - "traefik.http.services.ibkr-dashboard.loadbalancer.healthcheck.interval=30s" # Middleware: strip X-Accel-Buffering to prevent any upstream buffering of SSE - "traefik.http.middlewares.ibkr-sse-headers.headers.customResponseHeaders.X-Accel-Buffering=no" networks: - ibkr-net - traefik-public networks: ibkr-net: driver: bridge traefik-public: external: true name: ${TRAEFIK_NETWORK:-traefik-public}