Files
microdao-daarion/noda1-docker-compose.node1.yml
Apple ef3473db21 snapshot: NODE1 production state 2026-02-09
Complete snapshot of /opt/microdao-daarion/ from NODE1 (144.76.224.179).
This represents the actual running production code that has diverged
significantly from the previous main branch.

Key changes from old main:
- Gateway (http_api.py): expanded from ~40KB to 164KB with full agent support
- Router: new /v1/agents/{id}/infer endpoint with vision + DeepSeek routing
- Behavior Policy: SOWA v2.2 (3-level: FULL/ACK/SILENT)
- Agent Registry: config/agent_registry.yml as single source of truth
- 13 agents configured (was 3)
- Memory service integration
- CrewAI teams and roles

Excluded from snapshot: venv/, .env, data/, backups, .tgz archives

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 08:46:46 -08:00

604 lines
17 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
- 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
volumes:
- ./services/router/router_config.yaml:/app/router_config.yaml:ro
- ./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:
- ./services/swapper-service/config/swapper_config_node1.yaml:/app/config/swapper_config.yaml:ro
- ./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:latest
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
- MEMORY_SERVICE_URL=http://memory-service:8000
- 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:
- ./gateway-bot:/app/gateway-bot:ro
- ./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
# 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:latest
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:
- ./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
# 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:
- ./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
- ./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:
- ./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:
- ./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:
- ./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
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
networks:
dagi-network:
external: true