# docker-compose.yml — Multi-Swarm Coevolutive # # Due servizi della strategia crypto, condividono la stessa immagine # `multi-swarm-coevolutive:dev` buildata dal Dockerfile root (uv workspace): # # * strategy-crypto-paper — paper-trading runner long-running # (scripts/run_paper_trading.py) # * strategy-crypto-gui — NiceGUI dashboard esposta da Traefik su # https://swarm.${DOMAIN_NAME:-tielogic.xyz}/strategy_crypto_gui # # Entrambi joinano la rete external `traefik` cosi' il client Cerbero # risolve direttamente l'host `cerbero-mcp` (porta 9000) senza passare # dal gateway pubblico ne' dal TLS. # # Pattern N strategie future: aggiungere strategy--paper + strategy--gui # con PathPrefix(/strategy__gui) e DASHBOARD_ROOT_PATH dedicato. # # Dati persistenti via bind mount dalla cartella del repo: # ./data cache OHLCV intermedia # ./series cache parquet per timeframe/symbol # ./state contiene runs.db (GA) + strategy_crypto.db (paper) + WAL/SHM # ./src/strategy_crypto/strategy_crypto/strategies JSON freezate (ro) # # Secrets (token Cerbero + OpenRouter): caricati da .env via env_file. networks: traefik: external: true x-swarm-env: &swarm-env # Override: rotta interna verso cerbero-mcp (no TLS, no traefik hop) CERBERO_BASE_URL: http://cerbero-mcp:9000 # Override: path container per persistenza DATA_DIR: /app/data SERIES_DIR: /app/series # DB separati per dominio: GA_DB_PATH: /app/state/runs.db STRATEGY_CRYPTO_DB_PATH: /app/state/strategy_crypto.db # Subpath sotto cui la dashboard NiceGUI e' esposta da Traefik DASHBOARD_ROOT_PATH: /strategy_crypto_gui services: strategy-crypto-paper: build: context: . dockerfile: Dockerfile image: multi-swarm-coevolutive:dev container_name: strategy-crypto-paper restart: unless-stopped networks: [traefik] env_file: .env environment: <<: *swarm-env volumes: - ./data:/app/data - ./series:/app/series - ./state:/app/state - ./src/strategy_crypto/strategy_crypto/strategies:/app/strategies:ro # Niente HTTP da controllare: ci affidiamo a `restart: unless-stopped` # e ai log per la liveness del runner. command: - python - /app/scripts/run_paper_trading.py - --name=${PAPER_RUN_NAME:-phase3-papertrade-prod} - --initial-capital=${PAPER_INITIAL_CAPITAL:-1000} - --fees-bp=${PAPER_FEES_BP:-5.0} - --poll-seconds=${PAPER_POLL_SECONDS:-300} - --lookback-bars=${PAPER_LOOKBACK_BARS:-500} - --strategies-dir=/app/strategies labels: - com.centurylinklabs.watchtower.enable=true strategy-crypto-gui: image: multi-swarm-coevolutive:dev build: context: . dockerfile: Dockerfile container_name: strategy-crypto-gui restart: unless-stopped networks: [traefik] env_file: .env environment: <<: *swarm-env volumes: # Dashboard legge entrambi i DB: state/ in read-only (WAL: vedi nota) - ./state:/app/state:ro - ./data:/app/data:ro - ./series:/app/series:ro entrypoint: - python - -m - strategy_crypto.frontend.nicegui_app command: [] healthcheck: test: - "CMD" - "python" - "-c" - "import os, urllib.request; urllib.request.urlopen(f'http://localhost:{os.environ.get(\"SWARM_DASHBOARD_PORT\",\"8080\")}/', timeout=3).close()" interval: 30s timeout: 5s retries: 3 start_period: 30s labels: - traefik.enable=true - traefik.docker.network=traefik - "traefik.http.routers.strategy-crypto-gui.rule=Host(`swarm.${DOMAIN_NAME:-tielogic.xyz}`) && PathPrefix(`/strategy_crypto_gui`)" - traefik.http.routers.strategy-crypto-gui.tls=true - traefik.http.routers.strategy-crypto-gui.entrypoints=websecure - traefik.http.routers.strategy-crypto-gui.tls.certresolver=mytlschallenge - "traefik.http.services.strategy-crypto-gui.loadbalancer.server.port=${SWARM_DASHBOARD_PORT:-8080}" # StripPrefix: rimuove /strategy_crypto_gui prima di girare al container. # NiceGUI ha root_path=/strategy_crypto_gui per generare link assoluti corretti # (lato browser), ma le route FastAPI interne restano "/", "/paper", ecc. — # quindi il prefix esterno DEVE essere stripped dal proxy. - "traefik.http.middlewares.strategy-crypto-stripprefix.stripprefix.prefixes=/strategy_crypto_gui" - "traefik.http.routers.strategy-crypto-gui.middlewares=strategy-crypto-stripprefix" - com.centurylinklabs.watchtower.enable=true