# docker-compose.ecosystem.yml — Full ByteLyst Ecosystem # # Brings up all infrastructure, platform services, dashboards, and product # backends + web apps in a single Docker Compose stack. # # Prerequisites: # 1. Copy .env.ecosystem.example → .env.ecosystem and fill in values # 2. All product repos must be sibling directories of this repo # # Usage: # GITEA_NPM_TOKEN= docker compose -f docker-compose.ecosystem.yml --env-file .env.ecosystem up --build # # The GITEA_NPM_TOKEN env var is required for product Docker builds that install # @bytelyst/* packages from the local Gitea npm registry via BuildKit secrets. # # Port Map: # Infrastructure: cosmos-emulator 8081, azurite 10000, mailpit 1025/8025, # loki 3100, grafana 3000, traefik 80/8080 # Phase 2 (opt-in): prometheus 9090, valkey 6379 # Platform: platform-service 4003, extraction-service 4005, mcp-server 4007 # Dashboards: admin-web 3001, tracker-web 3003 # Products: peakpulse 4010, chronomind 4011, jarvisjr 4012, # nomgap 4013, mindlyst 4014, lysnrai 4015, # notelett 4016, flowmonk 4017, actiontrail 4018, # localmemgpt 4019, efforise 4020 # Product webs: chronomind 3030, jarvisjr 3035, flowmonk 3040, # notelett 3045, mindlyst 3050, nomgap 3055, # actiontrail 3060, localmemgpt 3070, lysnrai 3002, # efforise 3080 # Product Dockerfiles require BuildKit secrets for Gitea npm registry access. # GITEA_NPM_HOST defaults to host.docker.internal (Mac local dev). x-product-build: &product-build args: GITEA_NPM_HOST: ${GITEA_NPM_HOST:-host.docker.internal} secrets: - gitea_npm_token secrets: gitea_npm_token: environment: GITEA_NPM_TOKEN services: # ═════════════════════════════════════════════════════════════════ # INFRASTRUCTURE # ═════════════════════════════════════════════════════════════════ cosmos-emulator: image: mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview ports: - '8081:8081' - '1234:1234' environment: - PROTOCOL=http - ENABLE_EXPLORER=true - GATEWAY_PUBLIC_ENDPOINT=cosmos-emulator healthcheck: test: ['CMD-SHELL', 'curl -sf http://127.0.0.1:8080/ready || exit 1'] interval: 10s timeout: 5s retries: 12 start_period: 20s restart: unless-stopped azurite: image: mcr.microsoft.com/azure-storage/azurite:3.35.0 command: azurite-blob --blobHost 0.0.0.0 --blobPort 10000 --location /data --skipApiVersionCheck ports: - '10000:10000' volumes: - azurite-data:/data healthcheck: test: ['CMD', 'nc', '-z', '127.0.0.1', '10000'] interval: 10s timeout: 5s retries: 6 restart: unless-stopped mailpit: image: axllent/mailpit:v1.27.5 ports: - '1025:1025' - '8025:8025' healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:8025'] interval: 10s timeout: 5s retries: 6 restart: unless-stopped loki: image: grafana/loki:3.3.2 ports: - '3100:3100' volumes: - ./services/monitoring/loki/loki-config.yml:/etc/loki/local-config.yaml - loki-data:/loki command: -config.file=/etc/loki/local-config.yaml healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:3100/ready'] interval: 15s timeout: 5s retries: 3 restart: unless-stopped grafana: image: grafana/grafana:11.4.0 ports: - '3000:3000' environment: - GF_SECURITY_ADMIN_USER=admin - GF_SECURITY_ADMIN_PASSWORD=bytelyst - GF_USERS_ALLOW_SIGN_UP=false volumes: - ./services/monitoring/grafana/provisioning:/etc/grafana/provisioning - ./services/monitoring/grafana/dashboards:/var/lib/grafana/dashboards - grafana-data:/var/lib/grafana depends_on: loki: condition: service_started healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:3000/api/health'] interval: 15s timeout: 5s retries: 3 restart: unless-stopped prometheus: image: prom/prometheus:v3.5.0 profiles: - phase2-observability command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' - '--web.enable-lifecycle' volumes: - ./services/monitoring/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro - prometheus-data:/prometheus depends_on: node-exporter: condition: service_started cadvisor: condition: service_started healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:9090/-/healthy'] interval: 15s timeout: 5s retries: 3 restart: unless-stopped node-exporter: image: prom/node-exporter:v1.9.1 profiles: - phase2-observability command: - '--path.rootfs=/host' - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($|/)' volumes: - /:/host:ro,rslave healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:9100/metrics'] interval: 15s timeout: 5s retries: 3 restart: unless-stopped cadvisor: image: gcr.io/cadvisor/cadvisor:v0.49.1 profiles: - phase2-observability privileged: true command: - '--housekeeping_interval=30s' - '--docker_only=true' volumes: - /:/rootfs:ro - /var/run:/var/run:rw - /sys:/sys:ro - /var/lib/docker:/var/lib/docker:ro - /dev/disk:/dev/disk:ro healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:8080/healthz'] interval: 15s timeout: 5s retries: 3 restart: unless-stopped valkey: image: valkey/valkey:8-alpine profiles: - phase2-shared command: - valkey-server - --save - '60' - '1' - --loglevel - warning volumes: - valkey-data:/data healthcheck: test: ['CMD', 'valkey-cli', 'ping'] interval: 10s timeout: 5s retries: 5 restart: unless-stopped gateway: image: traefik:v3.3 profiles: - legacy-gateway command: - '--api.insecure=true' - '--providers.docker=true' - '--providers.docker.exposedbydefault=false' - '--entrypoints.web.address=:80' - '--accesslog=true' - '--accesslog.format=json' ports: - '80:80' - '8080:8080' volumes: - /var/run/docker.sock:/var/run/docker.sock:ro depends_on: loki: condition: service_started restart: unless-stopped caddy: image: caddy:2-alpine container_name: caddy ports: - '80:80' - '443:443' volumes: - ../Caddyfile:/etc/caddy/Caddyfile:ro - caddy-data:/data - caddy-config:/config depends_on: platform-service: condition: service_healthy extraction-service: condition: service_healthy mcp-server: condition: service_healthy restart: unless-stopped # ═════════════════════════════════════════════════════════════════ # PLATFORM SERVICES (from this repo) # ═════════════════════════════════════════════════════════════════ platform-service: build: context: . dockerfile: services/platform-service/Dockerfile env_file: - .env.ecosystem environment: - PORT=4003 - COSMOS_AUTO_INIT=true - PLATFORM_SERVICE_URL=http://platform-service:4003 - EXTRACTION_SERVICE_URL=http://extraction-service:4005 - MCP_SERVER_URL=http://mcp-server:4007 - MAILPIT_UI_URL=http://mailpit:8025 depends_on: mailpit: condition: service_healthy azurite: condition: service_healthy cosmos-emulator: condition: service_healthy labels: - 'traefik.enable=true' - 'traefik.http.routers.platform.rule=PathPrefix(`/platform`)' - 'traefik.http.services.platform.loadbalancer.server.port=4003' healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:4003/health'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped extraction-service: build: context: . dockerfile: services/extraction-service/Dockerfile env_file: - .env.ecosystem environment: - PORT=4005 - PYTHON_SIDECAR_URL=http://localhost:4006 - PRODUCT_RATE_LIMIT_STORE=${PRODUCT_RATE_LIMIT_STORE:-valkey} - VALKEY_URL=${VALKEY_URL:-redis://valkey:6379} depends_on: cosmos-emulator: condition: service_healthy labels: - 'traefik.enable=true' - 'traefik.http.routers.extraction.rule=PathPrefix(`/extraction`)' - 'traefik.http.services.extraction.loadbalancer.server.port=4005' healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:4005/health'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped mcp-server: build: context: . dockerfile: services/mcp-server/Dockerfile env_file: - .env.ecosystem environment: - PORT=4007 - PLATFORM_SERVICE_URL=http://platform-service:4003 - EXTRACTION_SERVICE_URL=http://extraction-service:4005 depends_on: platform-service: condition: service_healthy extraction-service: condition: service_healthy labels: - 'traefik.enable=true' - 'traefik.http.routers.mcp.rule=PathPrefix(`/mcp`)' - 'traefik.http.services.mcp.loadbalancer.server.port=4007' healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:4007/health'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped # ═════════════════════════════════════════════════════════════════ # PLATFORM DASHBOARDS (from this repo) # ═════════════════════════════════════════════════════════════════ admin-web: build: context: . dockerfile: dashboards/admin-web/Dockerfile ports: - '3001:3001' env_file: - .env.ecosystem environment: - PORT=3001 - PLATFORM_SERVICE_URL=http://platform-service:4003 - EXTRACTION_SERVICE_URL=http://extraction-service:4005 - SEED_SECRET=${SEED_SECRET:-dev-seed-secret} depends_on: platform-service: condition: service_healthy healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:3001'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped tracker-web: build: context: . dockerfile: dashboards/tracker-web/Dockerfile ports: - '3003:3003' env_file: - .env.ecosystem environment: - PORT=3003 - PLATFORM_SERVICE_URL=http://platform-service:4003 - PLATFORM_API_URL=http://platform-service:4003 depends_on: platform-service: condition: service_healthy healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:3003'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped # ═════════════════════════════════════════════════════════════════ # PRODUCT BACKENDS (from sibling repos) # ═════════════════════════════════════════════════════════════════ peakpulse-backend: build: <<: *product-build context: ../learning_ai_peakpulse dockerfile: backend/Dockerfile env_file: - .env.ecosystem environment: - PORT=4010 - HOST=0.0.0.0 - PLATFORM_SERVICE_URL=http://platform-service:4003 depends_on: platform-service: condition: service_healthy healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:4010/health'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped chronomind-backend: build: <<: *product-build context: ../learning_ai_clock dockerfile: backend/Dockerfile env_file: - .env.ecosystem environment: - PORT=4011 - HOST=0.0.0.0 - PLATFORM_SERVICE_URL=http://platform-service:4003 depends_on: platform-service: condition: service_healthy healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:4011/health'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped jarvisjr-backend: build: <<: *product-build context: ../learning_ai_jarvis_jr dockerfile: backend/Dockerfile env_file: - .env.ecosystem environment: - PORT=4012 - HOST=0.0.0.0 - PLATFORM_SERVICE_URL=http://platform-service:4003 depends_on: platform-service: condition: service_healthy healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:4012/health'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped nomgap-backend: build: <<: *product-build context: ../learning_ai_fastgap dockerfile: backend/Dockerfile env_file: - .env.ecosystem environment: - PORT=4013 - HOST=0.0.0.0 - PLATFORM_SERVICE_URL=http://platform-service:4003 depends_on: platform-service: condition: service_healthy healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:4013/health'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped mindlyst-backend: build: <<: *product-build context: ../learning_multimodal_memory_agents dockerfile: backend/Dockerfile env_file: - .env.ecosystem environment: - PORT=4014 - HOST=0.0.0.0 - PLATFORM_SERVICE_URL=http://platform-service:4003 depends_on: platform-service: condition: service_healthy healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:4014/health'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped lysnrai-backend: build: <<: *product-build context: ../learning_voice_ai_agent dockerfile: backend/Dockerfile env_file: - .env.ecosystem environment: - PORT=4015 - HOST=0.0.0.0 - PLATFORM_SERVICE_URL=http://platform-service:4003 depends_on: platform-service: condition: service_healthy healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:4015/health'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped notelett-backend: build: <<: *product-build context: ../learning_ai_notes dockerfile: backend/Dockerfile env_file: - .env.ecosystem environment: - PORT=4016 - HOST=0.0.0.0 - PLATFORM_SERVICE_URL=http://platform-service:4003 - EXTRACTION_SERVICE_URL=http://extraction-service:4005 depends_on: platform-service: condition: service_healthy healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:4016/health'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped flowmonk-backend: build: <<: *product-build context: ../learning_ai_flowmonk dockerfile: backend/Dockerfile env_file: - .env.ecosystem environment: - PORT=4017 - HOST=0.0.0.0 - PLATFORM_SERVICE_URL=http://platform-service:4003 depends_on: platform-service: condition: service_healthy healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:4017/health'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped actiontrail-backend: build: <<: *product-build context: ../learning_ai_trails dockerfile: backend/Dockerfile env_file: - .env.ecosystem environment: - PORT=4018 - HOST=0.0.0.0 - PLATFORM_SERVICE_URL=http://platform-service:4003 depends_on: platform-service: condition: service_healthy healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:4018/health'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped localmemgpt-backend: build: <<: *product-build context: ../learning_ai_local_memory_gpt dockerfile: backend/Dockerfile extra_hosts: - 'host.docker.internal:host-gateway' env_file: - .env.ecosystem environment: - PORT=4019 - HOST=0.0.0.0 - OLLAMA_URL=http://host.docker.internal:11434 - PLATFORM_SERVICE_URL=http://platform-service:4003 volumes: - localmemgpt-data:/app/db depends_on: platform-service: condition: service_healthy healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:4019/health'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped efforise-backend: build: <<: *product-build context: ../learning_ai_efforise dockerfile: backend/Dockerfile ports: - '4020:4020' env_file: - .env.ecosystem environment: - PORT=4020 - HOST=0.0.0.0 - PLATFORM_SERVICE_URL=http://platform-service:4003 depends_on: platform-service: condition: service_healthy healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:4020/health'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped # ═════════════════════════════════════════════════════════════════ # PRODUCT WEB APPS (from sibling repos) # ═════════════════════════════════════════════════════════════════ lysnrai-dashboard: build: <<: *product-build context: ../learning_voice_ai_agent dockerfile: user-dashboard-web/Dockerfile args: GITEA_NPM_HOST: ${GITEA_NPM_HOST:-host.docker.internal} # NEXT_PUBLIC_* args are baked at build time for browser-side code NEXT_PUBLIC_PLATFORM_SERVICE_URL: http://localhost:4003 NEXT_PUBLIC_PRODUCT_ID: lysnrai ports: - '3002:3002' environment: - NODE_ENV=production - PORT=3002 # Non-prefixed vars are used by server-side code (API routes, SSR) - PLATFORM_SERVICE_URL=http://platform-service:4003 - ACTIONTRAIL_SERVICE_URL=http://actiontrail-backend:4018 depends_on: lysnrai-backend: condition: service_healthy healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:3002'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped chronomind-web: build: <<: *product-build context: ../learning_ai_clock dockerfile: web/Dockerfile args: GITEA_NPM_HOST: ${GITEA_NPM_HOST:-host.docker.internal} NEXT_PUBLIC_BACKEND_URL: http://localhost:4011 NEXT_PUBLIC_PLATFORM_SERVICE_URL: http://localhost:4003 ports: - '3030:3030' environment: - NODE_ENV=production - PORT=3030 - BACKEND_URL=http://chronomind-backend:4011 - PLATFORM_SERVICE_URL=http://platform-service:4003 depends_on: chronomind-backend: condition: service_healthy healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:3030'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped jarvisjr-web: build: <<: *product-build context: ../learning_ai_jarvis_jr dockerfile: web/Dockerfile args: GITEA_NPM_HOST: ${GITEA_NPM_HOST:-host.docker.internal} NEXT_PUBLIC_PLATFORM_SERVICE_URL: http://localhost:4003 ports: - '3035:3035' environment: - NODE_ENV=production - PORT=3035 - PLATFORM_SERVICE_URL=http://platform-service:4003 depends_on: jarvisjr-backend: condition: service_healthy healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:3035'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped flowmonk-web: build: <<: *product-build context: ../learning_ai_flowmonk dockerfile: web/Dockerfile args: GITEA_NPM_HOST: ${GITEA_NPM_HOST:-host.docker.internal} NEXT_PUBLIC_API_URL: http://localhost:4017 NEXT_PUBLIC_PLATFORM_URL: http://localhost:4003/api ports: - '3040:3040' environment: - NODE_ENV=production - PORT=3040 - API_URL=http://flowmonk-backend:4017 - PLATFORM_URL=http://platform-service:4003/api depends_on: flowmonk-backend: condition: service_healthy healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:3040'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped notelett-web: build: <<: *product-build context: ../learning_ai_notes dockerfile: web/Dockerfile args: GITEA_NPM_HOST: ${GITEA_NPM_HOST:-host.docker.internal} NEXT_PUBLIC_NOTES_API_URL: http://localhost:4016/api NEXT_PUBLIC_PLATFORM_SERVICE_URL: http://localhost:4003/api ports: - '3045:3045' environment: - NODE_ENV=production - PORT=3045 - NOTES_API_URL=http://notelett-backend:4016/api - PLATFORM_SERVICE_URL=http://platform-service:4003/api depends_on: notelett-backend: condition: service_healthy healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:3045'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped mindlyst-web: build: <<: *product-build context: ../learning_multimodal_memory_agents dockerfile: mindlyst-native/web/Dockerfile args: GITEA_NPM_HOST: ${GITEA_NPM_HOST:-host.docker.internal} NEXT_PUBLIC_PLATFORM_SERVICE_URL: http://localhost:4003 ports: - '3050:3050' environment: - NODE_ENV=production - PORT=3050 - PLATFORM_SERVICE_URL=http://platform-service:4003 depends_on: mindlyst-backend: condition: service_healthy healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:3050'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped nomgap-web: build: <<: *product-build context: ../learning_ai_fastgap dockerfile: web/Dockerfile args: GITEA_NPM_HOST: ${GITEA_NPM_HOST:-host.docker.internal} NEXT_PUBLIC_NOMGAP_API_URL: http://localhost:4013/api NEXT_PUBLIC_PLATFORM_SERVICE_URL: http://localhost:4003/api ports: - '3055:3055' environment: - NODE_ENV=production - PORT=3055 - NOMGAP_API_URL=http://nomgap-backend:4013/api - PLATFORM_SERVICE_URL=http://platform-service:4003/api depends_on: nomgap-backend: condition: service_healthy healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:3055'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped actiontrail-web: build: <<: *product-build context: ../learning_ai_trails dockerfile: web/Dockerfile args: GITEA_NPM_HOST: ${GITEA_NPM_HOST:-host.docker.internal} NEXT_PUBLIC_API_URL: http://localhost:4018 NEXT_PUBLIC_PLATFORM_URL: http://localhost:4003 ports: - '3060:3060' environment: - NODE_ENV=production - PORT=3060 - API_URL=http://actiontrail-backend:4018 - PLATFORM_URL=http://platform-service:4003 depends_on: actiontrail-backend: condition: service_healthy healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:3060'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped localmemgpt-web: build: <<: *product-build context: ../learning_ai_local_memory_gpt dockerfile: web/Dockerfile args: GITEA_NPM_HOST: ${GITEA_NPM_HOST:-host.docker.internal} NEXT_PUBLIC_BACKEND_URL: http://localhost:4019 NEXT_PUBLIC_PLATFORM_URL: http://localhost:4003 ports: - '3070:3070' environment: - NODE_ENV=production - PORT=3070 - BACKEND_URL=http://localmemgpt-backend:4019 - PLATFORM_URL=http://platform-service:4003 depends_on: localmemgpt-backend: condition: service_healthy healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:3070'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped efforise-web: build: <<: *product-build context: ../learning_ai_efforise dockerfile: client/Dockerfile ports: - '3080:3080' depends_on: efforise-backend: condition: service_healthy healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:3080'] interval: 30s timeout: 10s retries: 3 restart: unless-stopped # ── Local LLM Lab (no backend — dashboard talks directly to Ollama) ── llmlab-dashboard: build: <<: *product-build context: ../learning_ai_local_llms dockerfile: dashboard/Dockerfile args: GITEA_NPM_HOST: ${GITEA_NPM_HOST:-host.docker.internal} OLLAMA_URL: http://host.docker.internal:11434 ports: - '3075:3075' environment: - NODE_ENV=production - PORT=3075 - OLLAMA_URL=http://host.docker.internal:11434 - OLLAMA_HOST=http://host.docker.internal:11434 extra_hosts: - 'host.docker.internal:host-gateway' healthcheck: test: ['CMD', 'wget', '-q', '--spider', 'http://127.0.0.1:3075'] interval: 15s timeout: 5s retries: 3 restart: unless-stopped # ═════════════════════════════════════════════════════════════════ # VOLUMES # ═════════════════════════════════════════════════════════════════ volumes: azurite-data: loki-data: grafana-data: prometheus-data: valkey-data: localmemgpt-data: caddy-data: caddy-config: