在開發機上一鍵啟動整套異構系統的技巧。
系統從單體走向微服務之後,地端開發的難度也跟著飆升。想測一個完整流程,你得:
光把環境跑起來,半天就過去了。而且新同事 clone 專案下來,第一件事就是來問你「欸這要怎麼跑」,問到你懷疑人生。
解法就是在專案根目錄寫好 docker-compose.yml,一行指令還原整套環境。精華如下:
services:
# ============ 基礎設施 ============
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: waferbi
POSTGRES_DB: waferbi_db
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-change_me_in_local_properties}
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U waferbi -d waferbi_db"]
interval: 10s
# ============ 核心微服務 ============
wafer-backend: # Python / FastAPI + Delta Lake
build: ./services/wafer-bi
ports:
- "8000:8000"
user-service: # Java / Spring Boot 3
build: ./services/user-service
environment:
POSTGRES_HOST: postgres
JWT_SECRET: ${JWT_SECRET:-local_dev_jwt_secret_must_be_at_least_32_bytes}
depends_on:
postgres:
condition: service_healthy # 確保 DB 就緒後才啟動
api-gateway: # Node.js / Express
build: ./services/api-gateway
ports:
- "8080:8080"
environment:
USER_SERVICE_HOST: user-service
WAFER_BI_HOST: wafer-backend
JWT_SECRET: ${JWT_SECRET:-local_dev_jwt_secret_must_be_at_least_32_bytes}
depends_on:
- user-service
- wafer-backend
實際跑起來的樣子(Image 有快取所以跑起來速度很快,容器依賴順序自動排好):

▲ docker compose up 一鍵啟動 + compose ps 全部 healthy
四個服務全部亮綠燈,前端再用 npm run dev 起 Vite(開發時要熱更新,所以前端不進容器)。打開系統的「系統狀態」頁面,三大服務全部 UP:

▲ Wafer BI 系統狀態頁:Api-Gateway、User-Service、Wafer-Bi 全部 UP
微服務啟動最怕「時序問題」:user-service 比 postgres 先起來,連不上資料庫直接 Crash。所以我們用 healthcheck 搭配 depends_on: condition: service_healthy,明確告訴 Docker:「等資料庫真的能接受連線了,再啟動我的 Java 服務」。
這裡分享一個我踩過的雷:Gateway 的 healthcheck 原本寫 wget --spider http://localhost:8080/healthz,結果容器永遠顯示 unhealthy。查了半天才發現——node:20-slim 這種瘦身 Image 裡根本沒有 wget,哭啊。解法是用 Node 自己來檢查,反正它一定在:
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD node -e "require('http').get('http://localhost:8080/healthz', r => process.exit(r.statusCode === 200 ? 0 : 1)).on('error', () => process.exit(1))"
注意到 YAML 中的 ${POSTGRES_PASSWORD:-...} 了嗎?敏感資訊透過外部 .env 注入,不寫死在代碼庫,這是基本資安好習慣。
另外又遇到一個坑:JWT 的 Secret 長度是有規範的。我原本的預設值只有 29 個字元,Java 端的 jjwt 直接回我一個 WeakKeyException——RFC 7518 規定 HMAC-SHA 的 key 至少要 256 bits(32 bytes)。所以連 placeholder 都要放滿 32 字元以上,不然本地一跑登入就立刻回 500 給你看。
開發機上通常不只跑一個專案。我機器上另一個專案的 Redis 佔住了 6379,compose 一起就直接 Bind for 0.0.0.0:6379 failed: port is already allocated。如果你的服務起不來,先 docker ps 看看是不是有別的容器在佔位子,不要急著怪 compose 哈哈。
有了 Docker Compose,我們終於可以把心力放在業務邏輯,而不是在本地環境設定中苦苦掙扎了。明天,正式進入 K8S 的世界!