kneron_model_converter/docker-compose.yml
jim800121chen aeaecb8c06 fix(compose): Phase 0.8b deploy blocker — env 透傳 + 命名規格
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>
2026-05-18 01:01:59 +08:00

200 lines
7.3 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.

##
# 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 ----------
#
# T10Phase 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 A2visionA → converter API key 認證1:1 internal trust===
# 不能給 default — 必須使用者明示設置;未設時 apiKeyMiddleware 對外 API 一律回 503。
# 兩端converter / visionA值必須完全一致rotate 時雙端同時更新。
- CONVERTER_API_KEY=${CONVERTER_API_KEY}
# === Phase 0.8b A7trust proxyaudit log forensic source_ip===
# stage Nginx 1 hop → 1prod cloud LB + Nginx → 2明確 CIDR 也支援
- TRUST_PROXY=${TRUST_PROXY:-loopback}
# === Member Center Token Endpointconverter → 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 concurrencyT10 修 D5===
- MAX_CONCURRENT_UPLOADS=${MAX_CONCURRENT_UPLOADS:-5}
- UPLOAD_RETRY_AFTER_SECONDS=${UPLOAD_RETRY_AFTER_SECONDS:-30}
# === Phase 0.8b Phase B/result rate limitper 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