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>
47 lines
1.9 KiB
Docker
47 lines
1.9 KiB
Docker
# Task Scheduler Dockerfile(Phase 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*.json,npm ci 後再 COPY 原始碼,避免改 src 就 invalidate npm install 層
|
||
COPY package*.json ./
|
||
# --omit=dev 對齊新版 npm(替代 --only=production);jest / 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 並改 owner(worker / 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"]
|