version: '3.8' services: # DAGI Router для NODE1 router: build: context: ./services/router dockerfile: Dockerfile container_name: dagi-router-node1 ports: - "9102:8000" environment: - NATS_URL=nats://nats:4222 - ROUTER_CONFIG_PATH=/app/router_config.yaml - LOG_LEVEL=info - NODE_ID=node-1-hetzner-gex44 - MEMORY_SERVICE_URL=http://memory-service:8000 # Timeout policy: Gateway (180s) > Router (60s) > LLM (30s) - ROUTER_TIMEOUT=180 - QDRANT_HOST=qdrant - QDRANT_PORT=6333 - QDRANT_ENABLED=true - NEO4J_BOLT_URL=bolt://neo4j:7687 - NEO4J_HTTP_URL=http://neo4j:7474 - NEO4J_USER=neo4j - NEO4J_PASSWORD=DaarionNeo4j2026! - DEEPSEEK_API_KEY=sk-0db94e8193ec4a6e9acd593ee8d898e7 - MISTRAL_API_KEY=40Gwjo8nVBx4i4vIkgszvXw9bOwDOu4G - COHERE_API_KEY=nOdOXnuepLku2ipJWpe6acWgAsJCsDhMO0RnaEJB - GROK_API_KEY=xai-69zEnDse8qRuQyZATs9jVKgfwdyvkHzgEVrTbV0OTAurZqsjHmvGepXG6H9GhVRYEC7E4NFl6iZeG0ww - VISION_ENCODER_URL=http://vision-encoder:8001 - SWAPPER_SERVICE_URL=http://swapper-service:8890 - IMAGE_GEN_URL=http://swapper-service:8890/image/generate - STT_SERVICE_URL=http://swapper-service:8890 - STT_SERVICE_UPLOAD_URL=http://swapper-service:8890/stt - OCR_SERVICE_URL=http://swapper-service:8890 - WEB_SEARCH_SERVICE_URL=http://swapper-service:8890 - ONEOK_CRM_BASE_URL=http://oneok-crm-adapter:8088 - ONEOK_CALC_BASE_URL=http://oneok-calc-adapter:8089 - ONEOK_DOCS_BASE_URL=http://oneok-docs-adapter:8090 - ONEOK_SCHEDULE_BASE_URL=http://oneok-schedule-adapter:8091 - ONEOK_ADAPTER_API_KEY=${ONEOK_ADAPTER_API_KEY} - ROUTER_TOOL_MAX_ROUNDS=${ROUTER_TOOL_MAX_ROUNDS:-10} volumes: - ${DEPLOY_ROOT:-.}/services/router/router_config.yaml:/app/router_config.yaml:ro - ${DEPLOY_ROOT:-.}/services/router/router-config.yml:/app/router-config.yml:ro - ${DEPLOY_ROOT:-.}/config/crewai_agents.json:/config/crewai_agents.json:ro - ${DEPLOY_ROOT:-.}/logs:/app/logs networks: - dagi-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "python -c \"import urllib.request; urllib.request.urlopen('http://localhost:8000/health')\""] interval: 30s timeout: 10s retries: 3 start_period: 10s # Swapper Service для NODE1 - Dynamic LLM + OCR model loading swapper-service: build: context: ./services/swapper-service dockerfile: Dockerfile container_name: swapper-service-node1 ports: - "8890:8890" - "8891:8891" # Metrics environment: - OLLAMA_BASE_URL=http://172.18.0.1:11434 - SWAPPER_CONFIG_PATH=/app/config/swapper_config.yaml - SWAPPER_MODE=single-active - MAX_CONCURRENT_MODELS=2 # 1 LLM + 1 OCR - MODEL_SWAP_TIMEOUT=300 - GPU_ENABLED=true - NODE_ID=node-1-hetzner-gex44 - HF_HOME=/root/.cache/huggingface - CUDA_VISIBLE_DEVICES=0 - CRAWL4AI_URL=http://crawl4ai:11235 # Cloud API keys for video/image generation - GROK_API_KEY=xai-69zEnDse8qRuQyZATs9jVKgfwdyvkHzgEVrTbV0OTAurZqsjHmvGepXG6H9GhVRYEC7E4NFl6iZeG0ww - MISTRAL_API_KEY=40Gwjo8nVBx4i4vIkgszvXw9bOwDOu4G volumes: - ${DEPLOY_ROOT:-.}/services/swapper-service/config/swapper_config_node1.yaml:/app/config/swapper_config.yaml:ro - ${DEPLOY_ROOT:-.}/logs:/app/logs - swapper-hf-cache-node1:/root/.cache/huggingface # GPU support for OCR models deploy: resources: reservations: devices: - driver: nvidia count: 1 capabilities: [gpu] networks: - dagi-network restart: unless-stopped extra_hosts: - "host.docker.internal:172.18.0.1" healthcheck: test: ["CMD-SHELL", "wget -qO- http://localhost:8890/health || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 60s # Image Generation тепер інтегровано в Swapper Service (lazy loading) # Endpoint: POST /image/generate на swapper-service:8890 # Crawl4AI - Advanced Web Crawler with JavaScript support crawl4ai: image: unclecode/crawl4ai@sha256:4d8b065bf185962733cb5f9701f4122d03383fa1ab6b5f6a9873f04fa0416a84 container_name: dagi-crawl4ai-node1 ports: - "11235:11235" environment: - CRAWL4AI_API_TOKEN=${CRAWL4AI_API_TOKEN:-} - MAX_CONCURRENT_TASKS=5 networks: - dagi-network restart: unless-stopped healthcheck: test: ["CMD", "curl", "-f", "http://localhost:11235/health"] interval: 30s timeout: 10s retries: 3 start_period: 30s # Gateway Bot (Helion + DAARWIZZ) gateway: build: context: ./gateway-bot dockerfile: Dockerfile container_name: dagi-gateway-node1 ports: - "9300:9300" environment: - ROUTER_URL=http://router:8000 - SERVICE_ID=gateway - SERVICE_ROLE=gateway - BRAND_INTAKE_URL=http://brand-intake:9211 - BRAND_REGISTRY_URL=http://brand-registry:9210 - PRESENTATION_RENDERER_URL=http://presentation-renderer:9212 - ARTIFACT_REGISTRY_URL=http://artifact-registry:9220 - HELION_TELEGRAM_BOT_TOKEN=8112062582:AAGS-HwRLEI269lDutLtAJTFArsIq31YNhE - HELION_NAME=Helion - HELION_PROMPT_PATH=/app/gateway-bot/helion_prompt.txt - NUTRA_TELEGRAM_BOT_TOKEN=8517315428:AAGTLcKxBAZDsMgx28agKTvl1SqJGi0utH4 - NUTRA_NAME=NUTRA - DRUID_TELEGRAM_BOT_TOKEN=8145618489:AAFR714mBsNmiuF-rjCw-295iORBReJQZ70 - DRUID_NAME=Druid - DRUID_PROMPT_PATH=/app/gateway-bot/druid_prompt.txt - DAARWIZZ_TELEGRAM_BOT_TOKEN=8323412397:AAGZbAR22LuOiGD8xVC3OXMjahQ8rs2lJwo - DAARWIZZ_NAME=DAARWIZZ - DAARWIZZ_PROMPT_PATH=/app/gateway-bot/daarwizz_prompt.txt - GREENFOOD_TELEGRAM_BOT_TOKEN=7495165343:AAGR1XEOzg7DkPFPCzL_eYLCJfxJuonCxug - GREENFOOD_NAME=GREENFOOD - GREENFOOD_PROMPT_PATH=/app/gateway-bot/greenfood_prompt.txt - AGROMATRIX_TELEGRAM_BOT_TOKEN=8580290441:AAFuDBmFJtpl-3I_WfkH7Hkb59X0fhYNMOE - AGROMATRIX_NAME=AgroMatrix - AGROMATRIX_PROMPT_PATH=/app/gateway-bot/agromatrix_prompt.txt # Alateya - R&D, біотех, інновації - ALATEYA_TELEGRAM_BOT_TOKEN=8436880945:AAEi-HS6GEctddoqBUd37MHfweZQP-OjRlo - ALATEYA_NAME=Alateya - ALATEYA_PROMPT_PATH=/app/gateway-bot/alateya_prompt.txt # Clan (Spirit) - Дух Общини - CLAN_TELEGRAM_BOT_TOKEN=8516872152:AAHH26wU8hJZJbSCJXb4vbmPmakTP77ok5E - CLAN_NAME=Spirit - CLAN_PROMPT_PATH=/app/gateway-bot/clan_prompt.txt # Eonarch - Еволюція свідомості - EONARCH_TELEGRAM_BOT_TOKEN=7962391584:AAFYkelLRG3VR_Lxuu6pEGG76t4vZdANtz4 - EONARCH_NAME=EONARCH - EONARCH_PROMPT_PATH=/app/gateway-bot/eonarch_prompt.txt - SENPAI_TELEGRAM_BOT_TOKEN=8510265026:AAGFrFBIIEihsLptZSxuKdmW2RoRPQDY9FE - ONEOK_TELEGRAM_BOT_TOKEN=${ONEOK_TELEGRAM_BOT_TOKEN} - SOUL_TELEGRAM_BOT_TOKEN=8041596416:AAHhpfCtY8paCm_9AD-4stJJg-Vw-CBf6Qk - YAROMIR_TELEGRAM_BOT_TOKEN=8128180674:AAGNZdG3LwECI4z_803smsuRHsK3nPdjMLY - SOFIIA_TELEGRAM_BOT_TOKEN=8589292566:AAEmPvS6nY9e-Y-TZm04CAHWlaFnWVxajE4 - SENPAI_NAME=SENPAI - ONEOK_NAME=1OK - SOUL_NAME=Athena - YAROMIR_NAME=Yaromir - SOFIIA_NAME=Sophia - SENPAI_PROMPT_PATH=/app/gateway-bot/senpai_prompt.txt - ONEOK_PROMPT_PATH=/app/gateway-bot/oneok_prompt.txt - MEMORY_SERVICE_URL=http://memory-service:8000 # Timeout policy: Gateway (180s) > Router (60s) > LLM (30s) - ROUTER_TIMEOUT=180 - SWAPPER_SERVICE_URL=http://swapper-service:8890 - IMAGE_GEN_URL=http://swapper-service:8890/image/generate - STT_SERVICE_URL=http://swapper-service:8890 - STT_SERVICE_UPLOAD_URL=http://swapper-service:8890/stt - OCR_SERVICE_URL=http://swapper-service:8890 - WEB_SEARCH_SERVICE_URL=http://swapper-service:8890 volumes: - ${DEPLOY_ROOT:-.}/gateway-bot:/app/gateway-bot:ro - ${DEPLOY_ROOT:-.}/logs:/app/logs depends_on: - router - memory-service networks: - dagi-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "python -c \"import urllib.request; urllib.request.urlopen('http://localhost:9300/health')\""] interval: 30s timeout: 10s retries: 3 start_period: 10s # CLAN Consent Outbox Worker (Postgres event-store applier; no execute) clan-consent-outbox-worker: build: context: ./services/clan-consent-adapter dockerfile: Dockerfile container_name: clan-consent-outbox-worker command: ["python", "clan_consent_outbox_worker.py"] environment: - CLAN_PG_DSN=${CLAN_PG_DSN:-postgresql://daarion:DaarionDB2026!@dagi-postgres:5432/daarion_main} - CLAN_OUTBOX_BATCH_SIZE=${CLAN_OUTBOX_BATCH_SIZE:-10} - CLAN_OUTBOX_POLL_INTERVAL_SEC=${CLAN_OUTBOX_POLL_INTERVAL_SEC:-1.0} - CLAN_OUTBOX_MAX_CAS_RETRIES=${CLAN_OUTBOX_MAX_CAS_RETRIES:-5} - CLAN_CONSENT_APPLIER_ACTOR_ID=${CLAN_CONSENT_APPLIER_ACTOR_ID:-system:consent-applier} volumes: - ${DEPLOY_ROOT:-.}/logs:/app/logs depends_on: - dagi-postgres networks: - dagi-network restart: unless-stopped # 1OK - EspoCRM DB oneok-espocrm-db: image: mariadb:11 container_name: oneok-espocrm-db-node1 environment: - MARIADB_ROOT_PASSWORD=${ONEOK_ESPO_DB_ROOT_PASSWORD:-change_me_root} - MARIADB_DATABASE=${ONEOK_ESPO_DB_NAME:-oneok_espocrm} - MARIADB_USER=${ONEOK_ESPO_DB_USER:-oneok} - MARIADB_PASSWORD=${ONEOK_ESPO_DB_PASSWORD:-change_me_oneok} volumes: - oneok-espocrm-db-node1:/var/lib/mysql networks: - dagi-network restart: unless-stopped # 1OK - EspoCRM oneok-espocrm: image: espocrm/espocrm:latest container_name: oneok-espocrm-node1 ports: - "9080:80" environment: - ESPOCRM_DATABASE_HOST=oneok-espocrm-db - ESPOCRM_DATABASE_NAME=${ONEOK_ESPO_DB_NAME:-oneok_espocrm} - ESPOCRM_DATABASE_USER=${ONEOK_ESPO_DB_USER:-oneok} - ESPOCRM_DATABASE_PASSWORD=${ONEOK_ESPO_DB_PASSWORD:-change_me_oneok} - ESPOCRM_ADMIN_USERNAME=${ONEOK_ESPO_ADMIN_USER:-admin} - ESPOCRM_ADMIN_PASSWORD=${ONEOK_ESPO_ADMIN_PASSWORD:-change_me_admin} - ESPOCRM_SITE_URL=${ONEOK_ESPO_SITE_URL:-http://localhost:9080} depends_on: - oneok-espocrm-db networks: - dagi-network restart: unless-stopped # 1OK - Gotenberg PDF oneok-gotenberg: image: gotenberg/gotenberg:8 container_name: oneok-gotenberg-node1 command: - gotenberg - --api-timeout=30s - --api-port=3000 - --chromium-disable-routes=true ports: - "3010:3000" networks: - dagi-network restart: unless-stopped # 1OK - CRM Adapter oneok-crm-adapter: build: context: ./services/oneok-crm-adapter dockerfile: Dockerfile container_name: oneok-crm-adapter-node1 environment: - ONEOK_ADAPTER_API_KEY=${ONEOK_ADAPTER_API_KEY} - ONEOK_CRM_DB_PATH=/data/oneok_crm.sqlite - ONEOK_ESPO_URL=http://oneok-espocrm - ONEOK_ESPO_API_KEY=${ONEOK_ESPO_API_KEY} volumes: - oneok-crm-data-node1:/data depends_on: - oneok-espocrm networks: - dagi-network restart: unless-stopped # 1OK - Docs Adapter oneok-docs-adapter: build: context: ./services/oneok-docs-adapter dockerfile: Dockerfile container_name: oneok-docs-adapter-node1 environment: - ONEOK_ADAPTER_API_KEY=${ONEOK_ADAPTER_API_KEY} - ONEOK_GOTENBERG_URL=http://oneok-gotenberg:3000 depends_on: - oneok-gotenberg networks: - dagi-network restart: unless-stopped # 1OK - Calc Adapter oneok-calc-adapter: build: context: ./services/oneok-calc-adapter dockerfile: Dockerfile container_name: oneok-calc-adapter-node1 environment: - ONEOK_ADAPTER_API_KEY=${ONEOK_ADAPTER_API_KEY} - ONEOK_BASE_RATE_PER_M2=${ONEOK_BASE_RATE_PER_M2:-3200} - ONEOK_INSTALL_RATE_PER_M2=${ONEOK_INSTALL_RATE_PER_M2:-900} - ONEOK_CURRENCY=${ONEOK_CURRENCY:-UAH} networks: - dagi-network restart: unless-stopped # 1OK - Schedule Adapter oneok-schedule-adapter: build: context: ./services/oneok-schedule-adapter dockerfile: Dockerfile container_name: oneok-schedule-adapter-node1 environment: - ONEOK_ADAPTER_API_KEY=${ONEOK_ADAPTER_API_KEY} - ONEOK_SCHEDULE_TZ=Europe/Kyiv networks: - dagi-network restart: unless-stopped # NATS (JetStream) nats: image: nats:2.10-alpine container_name: dagi-nats-node1 ports: - "4222:4222" command: ["-js"] volumes: - nats-data-node1:/data networks: dagi-network: aliases: - nats restart: unless-stopped # MinIO Object Storage minio: image: minio/minio@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e container_name: dagi-minio-node1 ports: - "9000:9000" - "9001:9001" environment: - MINIO_ROOT_USER=minioadmin - MINIO_ROOT_PASSWORD=minioadmin command: ["server", "/data", "--console-address", ":9001"] volumes: - minio-data-node1:/data networks: - dagi-network restart: unless-stopped # Artifact Registry (shared for docs/presentations) artifact-registry: build: context: ./services/artifact-registry dockerfile: Dockerfile container_name: artifact-registry-node1 ports: - "9220:9220" environment: - POSTGRES_HOST=dagi-postgres - POSTGRES_PORT=5432 - POSTGRES_USER=daarion - POSTGRES_PASSWORD=DaarionDB2026! - POSTGRES_DB=daarion_main - MINIO_ENDPOINT=minio:9000 - MINIO_ACCESS_KEY=minioadmin - MINIO_SECRET_KEY=minioadmin - MINIO_BUCKET=artifacts - MINIO_SECURE=false - NATS_URL=nats://nats:4222 volumes: - ${DEPLOY_ROOT:-.}/logs:/app/logs depends_on: - nats - minio networks: - dagi-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "python -c \"import urllib.request; urllib.request.urlopen('http://localhost:9220/health')\""] interval: 30s timeout: 10s retries: 3 start_period: 10s # RAG Service (pgvector) rag-service: build: context: ./services/rag-service dockerfile: Dockerfile container_name: rag-service-node1 ports: - "9500:9500" environment: - PG_DSN=postgresql+psycopg2://daarion:DaarionDB2026!@dagi-postgres:5432/rag - RAG_TABLE_NAME=rag_documents depends_on: - dagi-postgres networks: - dagi-network restart: unless-stopped healthcheck: test: ["CMD", "wget", "-qO-", "http://localhost:9500/health"] interval: 10s timeout: 3s retries: 10 # PPTX Render Worker render-pptx-worker: build: context: ./services/render-pptx-worker dockerfile: Dockerfile container_name: render-pptx-worker-node1 environment: - NATS_URL=nats://nats:4222 - ARTIFACT_REGISTRY_URL=http://artifact-registry:9220 - MINIO_ENDPOINT=minio:9000 - MINIO_ACCESS_KEY=minioadmin - MINIO_SECRET_KEY=minioadmin - MINIO_BUCKET=artifacts - MINIO_SECURE=false depends_on: - nats - artifact-registry - minio networks: - dagi-network restart: unless-stopped # PDF Render Worker (LibreOffice) render-pdf-worker: build: context: ./services/render-pdf-worker dockerfile: Dockerfile container_name: render-pdf-worker-node1 environment: - NATS_URL=nats://nats:4222 - ARTIFACT_REGISTRY_URL=http://artifact-registry:9220 - MINIO_ENDPOINT=minio:9000 - MINIO_ACCESS_KEY=minioadmin - MINIO_SECRET_KEY=minioadmin - MINIO_BUCKET=artifacts - MINIO_SECURE=false depends_on: - nats - artifact-registry - minio networks: - dagi-network restart: unless-stopped stop_grace_period: 30s # Index Doc Worker index-doc-worker: build: context: ./services/index-doc-worker dockerfile: Dockerfile container_name: index-doc-worker-node1 environment: - NATS_URL=nats://nats:4222 - ARTIFACT_REGISTRY_URL=http://artifact-registry:9220 - RAG_SERVICE_URL=http://rag-service:9500 - MINIO_ENDPOINT=minio:9000 - MINIO_ACCESS_KEY=minioadmin - MINIO_SECRET_KEY=minioadmin - MINIO_BUCKET=artifacts - MINIO_SECURE=false - INDEX_DOC_MAX_BYTES=52428800 depends_on: - nats - artifact-registry - rag-service - minio networks: - dagi-network restart: unless-stopped # Brand Registry Service brand-registry: build: context: ./services/brand-registry dockerfile: Dockerfile container_name: brand-registry-node1 ports: - "9210:9210" environment: - BRAND_REGISTRY_DATA=/data/brand-registry volumes: - ${DEPLOY_ROOT:-.}/logs:/app/logs - brand-registry-data-node1:/data/brand-registry networks: - dagi-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "python -c \"import urllib.request; urllib.request.urlopen('http://localhost:9210/health')\""] interval: 30s timeout: 10s retries: 3 start_period: 10s # Brand Intake Service brand-intake: build: context: ./services/brand-intake dockerfile: Dockerfile container_name: brand-intake-node1 ports: - "9211:9211" environment: - BRAND_MAP_PATH=/app/config/BrandMap.yaml - BRAND_INTAKE_DATA=/data/brand-intake - BRAND_REGISTRY_URL=http://brand-registry:9210 volumes: - ./config/brand/BrandMap.yaml:/app/config/BrandMap.yaml:ro - ${DEPLOY_ROOT:-.}/logs:/app/logs - brand-intake-data-node1:/data/brand-intake depends_on: - brand-registry networks: - dagi-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "python -c \"import urllib.request; urllib.request.urlopen('http://localhost:9211/health')\""] interval: 30s timeout: 10s retries: 3 start_period: 10s # Presentation Renderer Service (MVP) presentation-renderer: build: context: ./services/presentation-renderer dockerfile: Dockerfile container_name: presentation-renderer-node1 ports: - "9212:9212" environment: - BRAND_REGISTRY_URL=http://brand-registry:9210 - PRESENTATION_DATA=/data/presentations volumes: - ${DEPLOY_ROOT:-.}/logs:/app/logs - presentation-data-node1:/data/presentations depends_on: - brand-registry networks: - dagi-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "python -c \"import urllib.request; urllib.request.urlopen('http://localhost:9212/health')\""] interval: 30s timeout: 10s retries: 3 start_period: 10s # Memory Service memory-service: build: context: ./services/memory-service dockerfile: Dockerfile container_name: dagi-memory-service-node1 ports: - "8000:8000" environment: # PostgreSQL connection (uses MEMORY_ prefix as per config.py) - MEMORY_POSTGRES_HOST=dagi-postgres - MEMORY_POSTGRES_PORT=5432 - MEMORY_POSTGRES_USER=daarion - MEMORY_POSTGRES_PASSWORD=DaarionDB2026! - MEMORY_POSTGRES_DB=daarion_memory # Qdrant connection - MEMORY_QDRANT_HOST=dagi-qdrant-node1 - MEMORY_QDRANT_PORT=6333 # Cohere for embeddings - MEMORY_COHERE_API_KEY=nOdOXnuepLku2ipJWpe6acWgAsJCsDhMO0RnaEJB - MEMORY_DEBUG=false volumes: - ${DEPLOY_ROOT:-.}/logs:/app/logs depends_on: - qdrant networks: - dagi-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "python -c \"import urllib.request; urllib.request.urlopen('http://localhost:8000/health')\""] interval: 30s timeout: 10s retries: 3 start_period: 10s # PostgreSQL (pgvector) dagi-postgres: image: pgvector/pgvector:pg16 container_name: dagi-postgres ports: - "5432:5432" environment: - POSTGRES_USER=daarion - POSTGRES_PASSWORD=DaarionDB2026! - POSTGRES_DB=daarion_main volumes: - postgres_data_node1:/var/lib/postgresql/data networks: - dagi-network restart: unless-stopped # Qdrant Vector Database qdrant: image: qdrant/qdrant:v1.7.4 container_name: dagi-qdrant-node1 ulimits: nofile: soft: 65536 hard: 65536 ports: - "6333:6333" # HTTP API - "6334:6334" # gRPC API volumes: - qdrant-data-node1:/qdrant/storage networks: - dagi-network restart: unless-stopped healthcheck: test: ["CMD", "true"] interval: 30s timeout: 10s retries: 3 # Neo4j Graph Database neo4j: image: neo4j:5.15-community container_name: dagi-neo4j-node1 ports: - "7474:7474" # HTTP - "7687:7687" # Bolt environment: - NEO4J_AUTH=neo4j/DaarionNeo4j2026! - NEO4J_PLUGINS=["apoc"] - NEO4J_dbms_memory_heap_initial__size=512m - NEO4J_dbms_memory_heap_max__size=2G volumes: - neo4j-data-node1:/data - neo4j-logs-node1:/logs networks: - dagi-network restart: unless-stopped healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:7474"] interval: 30s timeout: 10s retries: 3 # Redis Cache redis: image: redis:7-alpine container_name: dagi-redis-node1 ports: - "6379:6379" volumes: - redis-data-node1:/data networks: - dagi-network restart: unless-stopped healthcheck: test: ["CMD", "redis-cli", "PING"] interval: 30s timeout: 5s retries: 3 # Vision Encoder Service - OpenCLIP for text/image embeddings vision-encoder: build: context: ./services/vision-encoder dockerfile: Dockerfile container_name: dagi-vision-encoder-node1 ports: - "8001:8001" environment: - DEVICE=cpu # НОДА1 без GPU - MODEL_NAME=${VISION_MODEL_NAME:-ViT-L-14} - MODEL_PRETRAINED=${VISION_MODEL_PRETRAINED:-openai} - NORMALIZE_EMBEDDINGS=true - QDRANT_HOST=qdrant - QDRANT_PORT=6333 - QDRANT_ENABLED=true volumes: - ${DEPLOY_ROOT:-.}/logs:/app/logs - vision-model-cache-node1:/root/.cache/clip depends_on: - qdrant networks: - dagi-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "python -c \"import urllib.request; urllib.request.urlopen('http://localhost:8001/health')\""] interval: 30s timeout: 10s retries: 3 start_period: 60s # OCR тепер через Swapper Service (got-ocr2, donut-base, donut-cord моделі) # Explicit volume names to prevent prefix mismatch # This ensures volumes are always named consistently regardless of COMPOSE_PROJECT_NAME # E2E Agent Prober - monitors agent pipeline health agent-e2e-prober: build: context: ./services/agent-e2e-prober dockerfile: Dockerfile container_name: agent-e2e-prober-node1 ports: - "9108:9108" environment: - GATEWAY_URL=http://172.18.0.18:9300 - PROBE_INTERVAL=60 - PROBE_TIMEOUT=30 - METRICS_PORT=9108 networks: - dagi-network restart: unless-stopped depends_on: - gateway # === Market Data Pipeline (added 2026-02-09) === market-data-service: container_name: dagi-market-data-node1 restart: unless-stopped build: context: ./services/market-data-service dockerfile: Dockerfile environment: - BINANCE_WS_URL=wss://stream.binance.com:9443/ws - BYBIT_WS_URL=wss://stream.bybit.com/v5/public/spot - ALPACA_DRY_RUN=true - SQLITE_URL=sqlite+aiosqlite:////data/market_data.db - JSONL_PATH=/data/events.jsonl - HTTP_HOST=0.0.0.0 - HTTP_PORT=8891 - NATS_URL=nats://nats:4222 - NATS_ENABLED=true - NATS_SUBJECT_PREFIX=md.events - LOG_LEVEL=INFO - LOG_SAMPLE_RATE=500 ports: - "8893:8891" volumes: - market-data-node1:/data networks: - dagi-network depends_on: - nats command: ["run", "--provider", "binance,bybit", "--symbols", "BTCUSDT,ETHUSDT"] healthcheck: test: - CMD-SHELL - python -c "import urllib.request; urllib.request.urlopen('http://localhost:8891/health')" interval: 15s timeout: 5s retries: 3 start_period: 10s senpai-md-consumer: container_name: dagi-senpai-md-consumer-node1 restart: unless-stopped build: context: ./services/senpai-md-consumer dockerfile: Dockerfile environment: - NATS_URL=nats://nats:4222 - NATS_SUBJECT=md.events.> - NATS_QUEUE_GROUP=senpai-md - FEATURES_ENABLED=true - FEATURES_PUB_RATE_HZ=10 - FEATURES_PUB_SUBJECT=senpai.features - SIGNALS_PUB_SUBJECT=senpai.signals - ALERTS_PUB_SUBJECT=senpai.alerts - LOG_LEVEL=INFO - HTTP_PORT=8892 ports: - "8892:8892" networks: - dagi-network depends_on: nats: condition: service_started market-data-service: condition: service_healthy healthcheck: test: - CMD-SHELL - python -c "import urllib.request; urllib.request.urlopen('http://localhost:8892/health')" interval: 15s timeout: 10s retries: 5 start_period: 15s volumes: qdrant-data-node1: name: qdrant-data-node1 driver: local neo4j-data-node1: name: neo4j-data-node1 driver: local neo4j-logs-node1: name: neo4j-logs-node1 driver: local redis-data-node1: name: redis-data-node1 driver: local vision-model-cache-node1: name: vision-model-cache-node1 driver: local docling-model-cache-node1: name: docling-model-cache-node1 driver: local swapper-hf-cache-node1: name: swapper-hf-cache-node1 driver: local brand-registry-data-node1: name: brand-registry-data-node1 driver: local brand-intake-data-node1: name: brand-intake-data-node1 driver: local presentation-data-node1: name: presentation-data-node1 driver: local nats-data-node1: name: nats-data-node1 driver: local minio-data-node1: name: minio-data-node1 driver: local postgres_data_node1: name: postgres-data-node1 driver: local market-data-node1: name: market-data-node1 driver: local oneok-espocrm-db-node1: name: oneok-espocrm-db-node1 driver: local oneok-crm-data-node1: name: oneok-crm-data-node1 driver: local networks: dagi-network: external: true