############################################################################## # GoClaw Control Center — Docker Stack (Docker Swarm Production) # # Deploy: # docker stack deploy -c docker/docker-stack.yml goclaw # # Remove: # docker stack rm goclaw # # Scale gateway: # docker service scale goclaw_gateway=3 ############################################################################## version: "3.9" networks: goclaw-net: driver: overlay attachable: true volumes: ollama-data: driver: local mysql-data: driver: local configs: gateway-env: external: true secrets: mysql-root-password: external: true mysql-password: external: true jwt-secret: external: true services: # ── MySQL 8 ────────────────────────────────────────────────────────────── db: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD_FILE: /run/secrets/mysql-root-password MYSQL_DATABASE: goclaw MYSQL_USER: goclaw MYSQL_PASSWORD_FILE: /run/secrets/mysql-password secrets: - mysql-root-password - mysql-password volumes: - mysql-data:/var/lib/mysql networks: - goclaw-net deploy: replicas: 1 placement: constraints: - node.role == manager restart_policy: condition: on-failure delay: 10s resources: limits: memory: 1G reservations: memory: 512M healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 10s timeout: 5s retries: 5 start_period: 30s # ── Ollama LLM Server ───────────────────────────────────────────────────── ollama: image: ollama/ollama:latest volumes: - ollama-data:/root/.ollama networks: - goclaw-net deploy: replicas: 1 placement: constraints: # Pin to GPU node if available - node.labels.gpu == true restart_policy: condition: on-failure delay: 15s resources: limits: memory: 16G reservations: memory: 4G # GPU support via nvidia-container-runtime # Uncomment on GPU-enabled nodes: # runtime: nvidia # environment: # - NVIDIA_VISIBLE_DEVICES=all # ── Go Gateway (Orchestrator + Tool Executor) ───────────────────────────── gateway: image: git.softuniq.eu/uniqai/goclaw/gateway:latest environment: PORT: "18789" OLLAMA_BASE_URL: "http://ollama:11434" DATABASE_URL: "goclaw:{{MYSQL_PASSWORD}}@tcp(db:3306)/goclaw?parseTime=true" PROJECT_ROOT: "/app" REQUEST_TIMEOUT_SECS: "120" LOG_LEVEL: "info" secrets: - mysql-password networks: - goclaw-net ports: - target: 18789 published: 18789 protocol: tcp mode: ingress deploy: replicas: 2 update_config: parallelism: 1 delay: 10s order: start-first failure_action: rollback rollback_config: parallelism: 1 delay: 5s restart_policy: condition: on-failure delay: 5s max_attempts: 3 resources: limits: memory: 512M cpus: "1.0" reservations: memory: 128M cpus: "0.25" healthcheck: test: ["CMD", "wget", "-qO-", "http://localhost:18789/health"] interval: 15s timeout: 5s retries: 3 start_period: 10s # ── Control Center (React + Node.js) ───────────────────────────────────── control-center: image: git.softuniq.eu/uniqai/goclaw/control-center:latest environment: NODE_ENV: production DATABASE_URL: "mysql://goclaw:{{MYSQL_PASSWORD}}@db:3306/goclaw" GATEWAY_URL: "http://gateway:18789" secrets: - mysql-password - jwt-secret networks: - goclaw-net ports: - target: 3000 published: 3000 protocol: tcp mode: ingress deploy: replicas: 2 update_config: parallelism: 1 delay: 10s order: start-first failure_action: rollback rollback_config: parallelism: 1 delay: 5s restart_policy: condition: on-failure delay: 5s max_attempts: 3 resources: limits: memory: 1G cpus: "1.0" reservations: memory: 256M cpus: "0.25" healthcheck: test: ["CMD", "wget", "-qO-", "http://localhost:3000/api/health"] interval: 15s timeout: 5s retries: 3 start_period: 20s # ── Traefik Reverse Proxy (optional) ───────────────────────────────────── # traefik: # image: traefik:v3.0 # command: # - "--providers.docker.swarmMode=true" # - "--providers.docker.exposedbydefault=false" # - "--entrypoints.web.address=:80" # - "--entrypoints.websecure.address=:443" # - "--certificatesresolvers.letsencrypt.acme.email=admin@softuniq.eu" # - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json" # - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web" # ports: # - "80:80" # - "443:443" # volumes: # - /var/run/docker.sock:/var/run/docker.sock:ro # - traefik-certs:/letsencrypt # networks: # - goclaw-net # deploy: # placement: # constraints: # - node.role == manager