|
| 1 | +x-deploy-config: &deploy-config |
| 2 | + deploy: |
| 3 | + replicas: 2 |
| 4 | + placement: |
| 5 | + max_replicas_per_node: 1 |
| 6 | + constraints: |
| 7 | + - node.labels.socrates.enabled == true |
| 8 | + - node.labels.socrates.variant == ${DEPLOYMENT_ENV} |
| 9 | + preferences: |
| 10 | + - spread: node.labels.socrates.variant == ${DEPLOYMENT_ENV} |
| 11 | + update_config: |
| 12 | + parallelism: 1 |
| 13 | + delay: 10s |
| 14 | + failure_action: rollback |
| 15 | + resources: |
| 16 | + limits: |
| 17 | + cpus: ${CPU_LIMIT:-1} |
| 18 | + memory: ${MEMORY_LIMIT:-1G} |
| 19 | + reservations: |
| 20 | + memory: 512M |
| 21 | + restart_policy: |
| 22 | + condition: any |
| 23 | + labels: |
| 24 | + - org.freecodecamp.autoupdate=true |
| 25 | + |
| 26 | +x-port-config: &port-config |
| 27 | + target: 3000 |
| 28 | + protocol: tcp |
| 29 | + mode: host |
| 30 | + |
| 31 | +services: |
| 32 | + svc-socrates: |
| 33 | + image: ${DOCKER_REGISTRY}/${DEPLOYMENT_ENV}/socrates:${DEPLOYMENT_VERSION} |
| 34 | + ports: |
| 35 | + - published: 4010 |
| 36 | + <<: *port-config |
| 37 | + <<: *deploy-config |
| 38 | + healthcheck: |
| 39 | + test: |
| 40 | + [ |
| 41 | + "CMD-SHELL", |
| 42 | + "wget --no-verbose --spider http://localhost:3000/health || exit 1", |
| 43 | + ] |
| 44 | + interval: 30s |
| 45 | + timeout: 5s |
| 46 | + start_period: 15s |
| 47 | + retries: 3 |
| 48 | + environment: |
| 49 | + # Runtime |
| 50 | + - NODE_ENV=${NODE_ENV:-production} |
| 51 | + - PORT=3000 |
| 52 | + - SERVER_URL=${SERVER_URL} |
| 53 | + - ALLOWED_ORIGINS=${ALLOWED_ORIGINS:-*} |
| 54 | + - LOG_LEVEL=${LOG_LEVEL:-info} |
| 55 | + # Redis (overlay network service discovery) |
| 56 | + - REDIS_URL=redis://svc-redis:6379 |
| 57 | + # Authentication |
| 58 | + - API_KEY=${API_KEY} |
| 59 | + - DOCS_BASIC_AUTH_USER=${DOCS_BASIC_AUTH_USER} |
| 60 | + - DOCS_BASIC_AUTH_PASS=${DOCS_BASIC_AUTH_PASS} |
| 61 | + # Groq AI |
| 62 | + - GROQ_API_KEY=${GROQ_API_KEY} |
| 63 | + - GROQ_MODEL=${GROQ_MODEL:-openai/gpt-oss-20b} |
| 64 | + - GROQ_MODEL_HTML=${GROQ_MODEL_HTML:-openai/gpt-oss-20b} |
| 65 | + - GROQ_MODEL_CSS=${GROQ_MODEL_CSS:-openai/gpt-oss-20b} |
| 66 | + - GROQ_MODEL_JAVASCRIPT=${GROQ_MODEL_JAVASCRIPT:-openai/gpt-oss-120b} |
| 67 | + - GROQ_MODEL_PYTHON=${GROQ_MODEL_PYTHON:-openai/gpt-oss-120b} |
| 68 | + - GROQ_TIMEOUT_MS=${GROQ_TIMEOUT_MS:-30000} |
| 69 | + - GROQ_MAX_RETRIES=${GROQ_MAX_RETRIES:-2} |
| 70 | + - GROQ_BACKOFF_BASE_MS=${GROQ_BACKOFF_BASE_MS:-500} |
| 71 | + - GROQ_MAX_TOKENS=${GROQ_MAX_TOKENS:-1024} |
| 72 | + - GROQ_MAX_TOKENS_RETRY=${GROQ_MAX_TOKENS_RETRY:-2048} |
| 73 | + # Circuit Breaker |
| 74 | + - MODEL_CB_FAILURES=${MODEL_CB_FAILURES:-3} |
| 75 | + - MODEL_CB_COOLDOWN_MS=${MODEL_CB_COOLDOWN_MS:-30000} |
| 76 | + # Rate Limiting |
| 77 | + - PER_USER_LIMIT=${PER_USER_LIMIT:-10} |
| 78 | + - GLOBAL_LIMIT=${GLOBAL_LIMIT:-1000} |
| 79 | + |
| 80 | + svc-redis: |
| 81 | + image: redis:7.4-alpine |
| 82 | + command: ["redis-server", "--appendonly", "yes"] |
| 83 | + volumes: |
| 84 | + - redis_data:/data |
| 85 | + healthcheck: |
| 86 | + test: ["CMD", "redis-cli", "ping"] |
| 87 | + interval: 10s |
| 88 | + timeout: 5s |
| 89 | + start_period: 5s |
| 90 | + retries: 3 |
| 91 | + deploy: |
| 92 | + replicas: 1 |
| 93 | + placement: |
| 94 | + constraints: |
| 95 | + - node.labels.socrates.enabled == true |
| 96 | + - node.labels.socrates.variant == ${DEPLOYMENT_ENV} |
| 97 | + update_config: |
| 98 | + parallelism: 1 |
| 99 | + failure_action: rollback |
| 100 | + resources: |
| 101 | + limits: |
| 102 | + memory: 256M |
| 103 | + reservations: |
| 104 | + memory: 128M |
| 105 | + restart_policy: |
| 106 | + condition: any |
| 107 | + |
| 108 | +volumes: |
| 109 | + redis_data: |
0 commit comments