jim800121chen 4d381c0b50 feat(task-scheduler): Phase 1 — modularize server + add OAuth/JWKS + /api/v1/* routes
Refactor server.js (647 → 99 lines) into 30+ modules under src/:
- auth/: JWKS validation, JWT middleware, OAuth client_credentials
- routes/v1/: jobs (POST/GET/:id) + promote with input validation
- routes/legacy.js: existing /jobs multipart path (backward compatible)
- services/: jobService, healthService, sseService, statusMapper,
  doneListener
- middleware/: requestId, errorHandler, perClientRateLimit,
  uploadConcurrency, upload (multer + storage)
- redis/: Lua scripts for atomic claim/release_active_job
- storage/: local + minio adapters; fileAccessAgent/: PUT promote client
- config.js: env var validation with fail-fast

Phase 1 features (T1–T11):
- T1 Auth middleware + JWKS (Member Center OAuth2 resource server)
- T2 OAuth client (Member Center client_credentials, Basic auth)
- T3 /api/v1/* router skeleton
- T4 server.js refactor (legacy endpoints fully preserved, real-Redis
  regression verified — existing worker consumer group untouched)
- T5 POST /api/v1/jobs (multipart, OWASP-audited, 2 Critical / 6 Major
  fixed; Risk-A/B documented as accepted)
- T6 GET /api/v1/jobs + GET /:id (cursor pagination, ETag, IDOR-safe)
- T7 POST /jobs/:id/promote (FAA PUT with own service token, 300s
  timeout, fail-fast on missing FAA URL)
- T8 /health upgrade (healthy/degraded/unhealthy + 30s background cache)
- T9 stage_timings (release_active_job in terminal states)
- T10 env + Docker integration (MULTIPART_* + concurrency limiter)
- T11 README (498 lines) + OpenAPI 3.0 spec (1588 lines)

Tests: 630 pass across 29 suites. Updated Dockerfile + .dockerignore +
docker-compose.yml env passthrough (no hardcoded secrets, fail-fast on
missing required vars).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 10:55:05 +08:00

47 lines
1.9 KiB
Docker
Raw Permalink 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.

# Task Scheduler DockerfilePhase 1
#
# 設計重點T10 補強):
# 1. 用 node:18-alpine —— 最小化 image 大小(~150MB vs node:18 的 ~1GB
# 2. 兩階段:先複製 package*.json + npm ci再 COPY 其他檔,善用 Docker 層快取
# 3. 只裝 production deps--only=production / --omit=dev—— jest / nodemon 不進 image
# 4. 非 root user 執行,降低 RCE 後的影響面
# 5. .dockerignore 已排除 .env / tests / node_modules / IDE 設定
# 6. HEALTHCHECK 對接 /health 端點T8 已實作)
# 7. 環境變數透過 docker-compose / Kubernetes secret 注入,不在 image 內
FROM node:18-alpine
WORKDIR /app
# curl 只給 HEALTHCHECK 用alpine 預設無
RUN apk add --no-cache curl
# === 第一層:依賴(變動較少,快取友善)===
# 先 COPY package*.jsonnpm ci 後再 COPY 原始碼,避免改 src 就 invalidate npm install 層
COPY package*.json ./
# --omit=dev 對齊新版 npm替代 --only=productionjest / nodemon 等 devDependencies 不會被裝
RUN npm ci --omit=dev && npm cache clean --force
# === 第二層:原始碼 ===
# .dockerignore 已排除 .env / tests / __tests__ / node_modules這裡 COPY . . 是安全的
COPY . .
# === 安全:非 root user ===
RUN addgroup -g 1001 -S appgroup && \
adduser -S appuser -u 1001 -G appgroup
# 建立 job data dir 並改 ownerworker / scheduler 共用 volume 用)
RUN mkdir -p /data/jobs && chown -R appuser:appgroup /app /data/jobs
USER appuser
EXPOSE 4000
# Health check 對接 /health 端點T8含 redis / Member Center / FAA reachability
HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \
CMD curl -f http://localhost:4000/health || exit 1
# 啟動:直接 node server.js不用 npm start以利 SIGTERM signal 直接送到 node
# - npm start 會 fork 一層SIGTERM 不一定傳到 child影響 graceful shutdown
CMD ["node", "server.js"]