d8a9517 commit 漏改 docker-compose.yml:scheduler service environment block
沒透傳 Phase 0.8b 新 env、即使 stage .env 設了 container 也讀不到、
deploy 後 CONVERTER_API_KEY undefined 會啟動 503 reject all requests。
docker-compose.yml:
- 新增 10 個 Phase 0.8b env 透傳(CONVERTER_API_KEY 無 default fail-secure、
其他用 ${VAR:-default} fail-soft)
- 砍 9 個已廢 OAuth resource-server env(MEMBER_CENTER_ISSUER / JWKS_URL /
AUDIENCE / CONVERTER_TENANT_ID / SCOPE_* / JWKS_* / JWT_*)
- 保留 8 個 promote → FAA 用 env(MEMBER_CENTER_TOKEN_URL /
KNERON_CONVERTER_CLIENT_ID/SECRET / FILE_ACCESS_AGENT_* /
OAUTH_TOKEN_* / PROMOTE_TIMEOUT_MS)
docs/autoflow/04-architecture/api/api-result.md §16:
- 新增 Env Naming Reference Table(30 個 canonical env names)
- 拍板 source code 為 single source of truth、env.example 對齊
- 確認 /result 8 個 env + 其他 22 個的命名規格
- 留歷史記錄:Orchestrator 之前用過想像中縮寫名(_MAX / _HOURLY_QUOTA /
RESULT_CONCURRENT_STREAM_MAX)造成命名混亂、§16 為未來 prompt 引用標準
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
200 lines
7.3 KiB
YAML
200 lines
7.3 KiB
YAML
##
|
||
# Kneron Model Converter — Development docker-compose
|
||
#
|
||
# Usage:
|
||
# docker-compose up # local mode (shared volume)
|
||
# STORAGE_BACKEND=s3 docker-compose up # S3/MinIO mode
|
||
# docker-compose up --scale bie-worker=3 # scale BIE workers
|
||
##
|
||
|
||
volumes:
|
||
job-data:
|
||
|
||
services:
|
||
# ---------- Infrastructure ----------
|
||
|
||
redis:
|
||
image: redis:7-alpine
|
||
expose:
|
||
- "6379"
|
||
command: redis-server --save ""
|
||
healthcheck:
|
||
test: ["CMD", "redis-cli", "ping"]
|
||
interval: 5s
|
||
timeout: 3s
|
||
retries: 3
|
||
|
||
# ---------- Web UI ----------
|
||
|
||
web:
|
||
build: ./apps/web
|
||
ports:
|
||
- "9500:3000"
|
||
depends_on:
|
||
scheduler:
|
||
condition: service_healthy
|
||
restart: unless-stopped
|
||
|
||
# ---------- Scheduler ----------
|
||
#
|
||
# T10:Phase 1 env 透傳清單。所有值都用 ${VAR} 從 .env / shell 讀取,
|
||
# 不在 docker-compose.yml hardcode(避免 secret 被 commit)。
|
||
# 必填變數缺漏 → scheduler container 會啟動失敗(fail-fast)。
|
||
|
||
scheduler:
|
||
build: ./apps/task-scheduler
|
||
ports:
|
||
- "9501:4000"
|
||
depends_on:
|
||
redis:
|
||
condition: service_healthy
|
||
volumes:
|
||
- job-data:/data/jobs
|
||
environment:
|
||
# === 應用基本 ===
|
||
- PORT=4000
|
||
- NODE_ENV=${NODE_ENV:-development}
|
||
- LOG_LEVEL=${LOG_LEVEL:-info}
|
||
|
||
# === Redis ===
|
||
- REDIS_URL=redis://redis:6379
|
||
|
||
# === Job 資料目錄 / CORS ===
|
||
- JOB_DATA_DIR=/data/jobs
|
||
- FRONTEND_URL=${FRONTEND_URL:-http://localhost:9500}
|
||
|
||
# === Storage backend ===
|
||
- STORAGE_BACKEND=${STORAGE_BACKEND:-local}
|
||
- MINIO_ENDPOINT_URL=${MINIO_ENDPOINT_URL:-http://192.168.0.130:9000}
|
||
- MINIO_BUCKET=${MINIO_BUCKET:-convertet-working-space}
|
||
- MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY:-convuser}
|
||
- MINIO_SECRET_KEY=${MINIO_SECRET_KEY}
|
||
- MINIO_REGION=${MINIO_REGION:-us-east-1}
|
||
- MINIO_LIFECYCLE_DAYS=${MINIO_LIFECYCLE_DAYS:-7}
|
||
|
||
# === Phase 0.8b A2:visionA → converter API key 認證(1:1 internal trust)===
|
||
# 不能給 default — 必須使用者明示設置;未設時 apiKeyMiddleware 對外 API 一律回 503。
|
||
# 兩端(converter / visionA)值必須完全一致;rotate 時雙端同時更新。
|
||
- CONVERTER_API_KEY=${CONVERTER_API_KEY}
|
||
|
||
# === Phase 0.8b A7:trust proxy(audit log forensic source_ip)===
|
||
# stage Nginx 1 hop → 1;prod cloud LB + Nginx → 2;明確 CIDR 也支援
|
||
- TRUST_PROXY=${TRUST_PROXY:-loopback}
|
||
|
||
# === Member Center Token Endpoint(converter → FAA OAuth client 用,保留)===
|
||
# visionA → converter 已改 API key 不再走 OAuth/JWKS;但 converter promote
|
||
# 階段仍以 client_credentials grant 跟 Member Center 取 token、再 PUT 到 FAA。
|
||
- MEMBER_CENTER_TOKEN_URL=${MEMBER_CENTER_TOKEN_URL}
|
||
|
||
# === Converter OAuth Client 身份(converter → FAA 用,必填)===
|
||
- KNERON_CONVERTER_CLIENT_ID=${KNERON_CONVERTER_CLIENT_ID}
|
||
- KNERON_CONVERTER_CLIENT_SECRET=${KNERON_CONVERTER_CLIENT_SECRET}
|
||
|
||
# === File Access Agent(必填)===
|
||
- FILE_ACCESS_AGENT_BASE_URL=${FILE_ACCESS_AGENT_BASE_URL}
|
||
- FILE_ACCESS_AGENT_AUDIENCE=${FILE_ACCESS_AGENT_AUDIENCE}
|
||
|
||
# === OAuth Client cache(可選)===
|
||
- OAUTH_TOKEN_REFRESH_SKEW_MS=${OAUTH_TOKEN_REFRESH_SKEW_MS:-60000}
|
||
- OAUTH_TOKEN_TIMEOUT_MS=${OAUTH_TOKEN_TIMEOUT_MS:-10000}
|
||
|
||
# === Promote 行為(可選)===
|
||
- PROMOTE_TIMEOUT_MS=${PROMOTE_TIMEOUT_MS:-300000}
|
||
|
||
# === Multipart 上限(T10 修 D5)===
|
||
- MULTIPART_MODEL_MAX_BYTES=${MULTIPART_MODEL_MAX_BYTES:-524288000}
|
||
- MULTIPART_REF_IMAGE_MAX_BYTES=${MULTIPART_REF_IMAGE_MAX_BYTES:-10485760}
|
||
- MULTIPART_REF_IMAGES_MAX_COUNT=${MULTIPART_REF_IMAGES_MAX_COUNT:-100}
|
||
|
||
# === Upload concurrency(T10 修 D5)===
|
||
- MAX_CONCURRENT_UPLOADS=${MAX_CONCURRENT_UPLOADS:-5}
|
||
- UPLOAD_RETRY_AFTER_SECONDS=${UPLOAD_RETRY_AFTER_SECONDS:-30}
|
||
|
||
# === Phase 0.8b Phase B:/result rate limit(per token_fingerprint)===
|
||
# 命名以 §16.2.1 canonical names 為準(_PER_MIN + _WINDOW_MS 配對、不用 _MAX)
|
||
- RESULT_RATE_LIMIT_BURST_PER_10S=${RESULT_RATE_LIMIT_BURST_PER_10S:-5}
|
||
- RESULT_RATE_LIMIT_BURST_WINDOW_MS=${RESULT_RATE_LIMIT_BURST_WINDOW_MS:-10000}
|
||
- RESULT_RATE_LIMIT_SUSTAINED_PER_MIN=${RESULT_RATE_LIMIT_SUSTAINED_PER_MIN:-20}
|
||
- RESULT_RATE_LIMIT_SUSTAINED_WINDOW_MS=${RESULT_RATE_LIMIT_SUSTAINED_WINDOW_MS:-60000}
|
||
|
||
# === Phase 0.8b Phase B:/result bandwidth quota(保護 mass download)===
|
||
# 1 GiB = 1073741824 / 6 GiB = 6442450944
|
||
- RESULT_BANDWIDTH_QUOTA_PER_HOUR_BYTES=${RESULT_BANDWIDTH_QUOTA_PER_HOUR_BYTES:-1073741824}
|
||
- RESULT_BANDWIDTH_QUOTA_PER_DAY_BYTES=${RESULT_BANDWIDTH_QUOTA_PER_DAY_BYTES:-6442450944}
|
||
|
||
# === Phase 0.8b Phase B:/result concurrent stream cap + stream timeout ===
|
||
- MAX_CONCURRENT_RESULT_STREAMS=${MAX_CONCURRENT_RESULT_STREAMS:-10}
|
||
- RESULT_STREAM_TIMEOUT_MS=${RESULT_STREAM_TIMEOUT_MS:-300000}
|
||
restart: unless-stopped
|
||
|
||
# ---------- Workers (stub mode) ----------
|
||
|
||
onnx-worker:
|
||
build:
|
||
context: .
|
||
dockerfile: services/workers/Dockerfile.stub
|
||
depends_on:
|
||
redis:
|
||
condition: service_healthy
|
||
volumes:
|
||
- job-data:/data/jobs
|
||
environment:
|
||
- STAGE=onnx
|
||
- REDIS_URL=redis://redis:6379
|
||
- JOB_DATA_DIR=/data/jobs
|
||
- WORKER_MODE=${WORKER_MODE:-stub}
|
||
- STORAGE_BACKEND=${STORAGE_BACKEND:-local}
|
||
- MINIO_ENDPOINT_URL=${MINIO_ENDPOINT_URL:-http://192.168.0.130:9000}
|
||
- MINIO_BUCKET=${MINIO_BUCKET:-convertet-working-space}
|
||
- MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY:-convuser}
|
||
- MINIO_SECRET_KEY=${MINIO_SECRET_KEY}
|
||
- MINIO_REGION=${MINIO_REGION:-us-east-1}
|
||
- MINIO_LIFECYCLE_DAYS=${MINIO_LIFECYCLE_DAYS:-7}
|
||
restart: unless-stopped
|
||
|
||
bie-worker:
|
||
build:
|
||
context: .
|
||
dockerfile: services/workers/Dockerfile.stub
|
||
depends_on:
|
||
redis:
|
||
condition: service_healthy
|
||
volumes:
|
||
- job-data:/data/jobs
|
||
environment:
|
||
- STAGE=bie
|
||
- REDIS_URL=redis://redis:6379
|
||
- JOB_DATA_DIR=/data/jobs
|
||
- WORKER_MODE=${WORKER_MODE:-stub}
|
||
- STORAGE_BACKEND=${STORAGE_BACKEND:-local}
|
||
- MINIO_ENDPOINT_URL=${MINIO_ENDPOINT_URL:-http://192.168.0.130:9000}
|
||
- MINIO_BUCKET=${MINIO_BUCKET:-convertet-working-space}
|
||
- MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY:-convuser}
|
||
- MINIO_SECRET_KEY=${MINIO_SECRET_KEY}
|
||
- MINIO_REGION=${MINIO_REGION:-us-east-1}
|
||
- MINIO_LIFECYCLE_DAYS=${MINIO_LIFECYCLE_DAYS:-7}
|
||
restart: unless-stopped
|
||
|
||
nef-worker:
|
||
build:
|
||
context: .
|
||
dockerfile: services/workers/Dockerfile.stub
|
||
depends_on:
|
||
redis:
|
||
condition: service_healthy
|
||
volumes:
|
||
- job-data:/data/jobs
|
||
environment:
|
||
- STAGE=nef
|
||
- REDIS_URL=redis://redis:6379
|
||
- JOB_DATA_DIR=/data/jobs
|
||
- WORKER_MODE=${WORKER_MODE:-stub}
|
||
- STORAGE_BACKEND=${STORAGE_BACKEND:-local}
|
||
- MINIO_ENDPOINT_URL=${MINIO_ENDPOINT_URL:-http://192.168.0.130:9000}
|
||
- MINIO_BUCKET=${MINIO_BUCKET:-convertet-working-space}
|
||
- MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY:-convuser}
|
||
- MINIO_SECRET_KEY=${MINIO_SECRET_KEY}
|
||
- MINIO_REGION=${MINIO_REGION:-us-east-1}
|
||
- MINIO_LIFECYCLE_DAYS=${MINIO_LIFECYCLE_DAYS:-7}
|
||
restart: unless-stopped
|