結論先講
不要在本地跑所有微服務。 你正在改的功能只涉及 Order Service 和 Payment Service,那就只跑這兩個,其他的用 mock 或連到共用的 dev 環境。Docker Compose profile 可以輕鬆做到「選擇性啟動」。如果你的團隊已經上 K8s,Tilt 或 Skaffold 可以在本地 K8s cluster 跑,hot reload 不用重 build image。
本地全跑的慘況
docker compose up(全部啟動):
order-service 256MB
payment-service 256MB
user-service 256MB
notification-service 256MB
search-service 512MB
PostgreSQL 512MB
Redis 128MB
Kafka + Zookeeper 1.5GB
Elasticsearch 2GB
─────────────────────────
總計 ~5.7GB
加上你的 IDE(VS Code + TypeScript LSP):1-2GB
加上 Chrome(20 個分頁):2-3GB
加上 OS:2GB
─────────────────────────
總計:12-13GB → 16GB 的筆電開始 swap → 卡到想哭
解法一:Docker Compose Profile(選擇性啟動)
如同 第 42 篇 介紹的 Docker Compose,profiles 可以分組服務:
# docker-compose.yml
services:
# 核心服務——永遠啟動
postgres:
image: postgres:16-alpine
profiles: ["core"]
ports: ["5432:5432"]
redis:
image: redis:7-alpine
profiles: ["core"]
ports: ["6379:6379"]
# 按功能分組
order-service:
build: ./services/order
profiles: ["core", "order"]
depends_on: [postgres, redis]
payment-service:
build: ./services/payment
profiles: ["core", "payment"]
depends_on: [postgres]
# 重量級服務——需要時才啟動
kafka:
image: confluentinc/cp-kafka:7.6.0
profiles: ["event"]
elasticsearch:
image: elasticsearch:8.13.0
profiles: ["search"]
search-service:
build: ./services/search
profiles: ["search"]
depends_on: [elasticsearch]# 只跑 Order + Payment(改訂單功能時)
docker compose --profile core --profile order --profile payment up
# 需要搜尋功能時才加
docker compose --profile search up
# RAM 使用:core + order + payment ≈ 1.2GB(省了 4.5GB)解法二:Mock 不需要的服務
你在改 Order Service 的下單邏輯,需要呼叫 Payment Service。但你不需要「真的」跑 Payment Service:
// mock-payment-service.js(50 行搞定)
const express = require('express');
const app = express();
app.use(express.json());
// 模擬付款成功
app.post('/payments', (req, res) => {
console.log(`[Mock] Payment created: ${JSON.stringify(req.body)}`);
res.json({
id: `pay_${Date.now()}`,
status: 'succeeded',
amount: req.body.amount,
});
});
// 模擬付款查詢
app.get('/payments/:id', (req, res) => {
res.json({
id: req.params.id,
status: 'succeeded',
});
});
app.listen(3002, () => console.log('Mock Payment Service on :3002'));RAM 使用:30MB(vs 真正的 Payment Service 256MB)。
進階:用 WireMock 做 Mock Server
# docker-compose.override.yml(本地開發用)
services:
payment-mock:
image: wiremock/wiremock:3.5.2
volumes:
- ./mocks/payment:/home/wiremock/mappings
ports: ["3002:8080"]// mocks/payment/create-payment.json
{
"request": {
"method": "POST",
"url": "/payments"
},
"response": {
"status": 200,
"jsonBody": {
"id": "pay_mock_123",
"status": "succeeded"
}
}
}解法三:連到共用 Dev 環境
本地只跑你正在改的服務,其他服務連到 team 的 dev 環境:
本地:
order-service(你在改的)→ 連到 dev 環境的 payment-service
Dev 環境(K8s cluster):
payment-service
user-service
notification-service
kafka, postgres, redis, ES
# 設定環境變數,指向 dev 環境
PAYMENT_SERVICE_URL=https://dev.internal.mycompany.com/payment
USER_SERVICE_URL=https://dev.internal.mycompany.com/user注意:dev 環境的資料可能跟你本地不一致,debug 時要小心。
解法四:Tilt / Skaffold(本地 K8s 開發)
如果你的 production 跑 K8s,本地用 minikube + Tilt 可以模擬真實環境:
Tilt
# Tiltfile
# 只跑你需要的服務
docker_compose('./docker-compose.yml')
# Hot reload:改了 Go 程式碼 → 自動重新 build + deploy
local_resource(
'order-service',
serve_cmd='cd services/order && go run .',
deps=['services/order/'],
resource_deps=['postgres'],
)
# 其他服務用 mock
local_resource(
'payment-mock',
serve_cmd='node mocks/payment-mock.js',
)Tilt 的 dashboard 讓你一眼看到所有服務的狀態、log、build 進度。
Skaffold
# skaffold.yaml
apiVersion: skaffold/v4beta10
kind: Config
build:
artifacts:
- image: order-service
context: services/order
docker:
dockerfile: Dockerfile.dev
sync:
manual:
- src: '**/*.go'
dest: /app
deploy:
kubectl:
manifests:
- k8s/dev/*.yamlskaffold dev # 監聽檔案變更 → 自動 build + deploy 到本地 K8sHot Reload:改一行不要等 2 分鐘
最糟糕的開發體驗:
改一行程式碼
→ docker build(2 分鐘)
→ docker compose restart(30 秒)
→ 測試
→ 發現寫錯 → 再來一次
目標:
改一行程式碼 → 1-3 秒內生效
Docker Compose 的 Hot Reload
services:
order-service:
build:
context: ./services/order
dockerfile: Dockerfile.dev # 用 dev 版 Dockerfile
volumes:
- ./services/order/src:/app/src # 掛載原始碼
command: npm run dev # nodemon / ts-node-dev# Dockerfile.dev(不做 COPY,靠 volume mount)
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
# 不 COPY src——靠 volume mount
CMD ["npx", "nodemon", "src/index.ts"]我的建議:開發環境分層
Level 1 — 純本地(最快、最省 RAM):
只跑你在改的 1-2 個服務
其他全用 mock
DB 用 SQLite 或本地 PostgreSQL
RAM:1-2GB
Level 2 — 本地 + Dev 環境(平衡):
你在改的服務跑本地
其他服務連到 team 的 dev K8s cluster
RAM:1-2GB 本地 + 共用 dev 環境
Level 3 — 全本地 Docker Compose(最真實):
所有服務都跑本地
用 profile 控制啟動哪些
偶爾需要 end-to-end 測試時才用
RAM:6-8GB
Level 4 — Remote Dev Environment(最奢侈):
GitHub Codespaces / Gitpod / 自建 dev VM
在雲端跑所有服務
本地只跑 VS Code Remote
RAM:本地幾乎不佔
下一篇
Debug 跨服務問題 — 服務跑起來了,但用戶回報 bug:「下單失敗」。5 個服務、50 個 container、100 萬行 log——從哪裡開始查?
本系列文章
完整 68 篇目錄見 系列首頁
← 上一篇:微服務安全(二):API Gateway 的安全功能 → 下一篇:開發者體驗(二):Debug 跨服務問題的 SOP