feat: production docker-compose with health checks + resource limits (API-AI-077)
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 45s
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 45s
- Add health checks: api (GET /health), worker, heavy-runtime, nginx - Add resource limits (deploy.resources) for all 6 services - Add heavy-runtime service (Rust AI Worker) - Add INTERNAL_API_KEY + CREDENTIAL_ENCRYPTION_KEY env vars - nginx health check via GET /health Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
5c7b8d1855
commit
094f00553a
@ -1,6 +1,9 @@
|
|||||||
version: '3.8'
|
version: '3.8'
|
||||||
|
|
||||||
|
# ── 生产部署配置(含 health check、资源限制) ──
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
# ── MySQL 8.0 ──
|
||||||
mysql:
|
mysql:
|
||||||
image: mysql:8.0
|
image: mysql:8.0
|
||||||
container_name: zhixi-mysql
|
container_name: zhixi-mysql
|
||||||
@ -22,7 +25,16 @@ services:
|
|||||||
retries: 5
|
retries: 5
|
||||||
networks:
|
networks:
|
||||||
- zhixi-net
|
- zhixi-net
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '2'
|
||||||
|
memory: 2G
|
||||||
|
reservations:
|
||||||
|
cpus: '0.5'
|
||||||
|
memory: 512M
|
||||||
|
|
||||||
|
# ── Redis 7 ──
|
||||||
redis:
|
redis:
|
||||||
image: redis:7-alpine
|
image: redis:7-alpine
|
||||||
container_name: zhixi-redis
|
container_name: zhixi-redis
|
||||||
@ -38,7 +50,16 @@ services:
|
|||||||
retries: 5
|
retries: 5
|
||||||
networks:
|
networks:
|
||||||
- zhixi-net
|
- zhixi-net
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '0.5'
|
||||||
|
memory: 256M
|
||||||
|
reservations:
|
||||||
|
cpus: '0.1'
|
||||||
|
memory: 64M
|
||||||
|
|
||||||
|
# ── API Server (NestJS) ──
|
||||||
api:
|
api:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
@ -65,6 +86,8 @@ services:
|
|||||||
JWT_SECRET: ${JWT_SECRET:-change_me_in_production}
|
JWT_SECRET: ${JWT_SECRET:-change_me_in_production}
|
||||||
JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-1h}
|
JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-1h}
|
||||||
JWT_REFRESH_EXPIRES_IN: ${JWT_REFRESH_EXPIRES_IN:-7d}
|
JWT_REFRESH_EXPIRES_IN: ${JWT_REFRESH_EXPIRES_IN:-7d}
|
||||||
|
INTERNAL_API_KEY: ${INTERNAL_API_KEY:-change_me_runtime_key}
|
||||||
|
CREDENTIAL_ENCRYPTION_KEY: ${CREDENTIAL_ENCRYPTION_KEY:-change_me_32_bytes_key!!}
|
||||||
DEV_SECRET: ${DEV_SECRET:-}
|
DEV_SECRET: ${DEV_SECRET:-}
|
||||||
APPLE_BUNDLE_ID: ${APPLE_BUNDLE_ID:-cloud.longde.AIStudyApp}
|
APPLE_BUNDLE_ID: ${APPLE_BUNDLE_ID:-cloud.longde.AIStudyApp}
|
||||||
APPLE_ISSUER: ${APPLE_ISSUER:-https://appleid.apple.com}
|
APPLE_ISSUER: ${APPLE_ISSUER:-https://appleid.apple.com}
|
||||||
@ -84,9 +107,24 @@ services:
|
|||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
redis:
|
redis:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
healthcheck:
|
||||||
|
test: ['CMD', 'wget', '-qO-', 'http://localhost:3000/health']
|
||||||
|
interval: 15s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 3
|
||||||
|
start_period: 30s
|
||||||
networks:
|
networks:
|
||||||
- zhixi-net
|
- zhixi-net
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '2'
|
||||||
|
memory: 1G
|
||||||
|
reservations:
|
||||||
|
cpus: '0.5'
|
||||||
|
memory: 256M
|
||||||
|
|
||||||
|
# ── API Worker (Prisma CRON / Queue) ──
|
||||||
worker:
|
worker:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
@ -102,12 +140,10 @@ services:
|
|||||||
REDIS_PASSWORD: ''
|
REDIS_PASSWORD: ''
|
||||||
REDIS_DB: '0'
|
REDIS_DB: '0'
|
||||||
AI_PROVIDER: ${AI_PROVIDER:-mock}
|
AI_PROVIDER: ${AI_PROVIDER:-mock}
|
||||||
AI_DEFAULT_TIER: ${AI_DEFAULT_TIER:-primary}
|
|
||||||
DEEPSEEK_API_KEY: ${DEEPSEEK_API_KEY:-}
|
DEEPSEEK_API_KEY: ${DEEPSEEK_API_KEY:-}
|
||||||
DEEPSEEK_BASE_URL: ${DEEPSEEK_BASE_URL:-https://api.deepseek.com}
|
DEEPSEEK_BASE_URL: ${DEEPSEEK_BASE_URL:-https://api.deepseek.com}
|
||||||
MINIMAX_API_KEY: ${MINIMAX_API_KEY:-}
|
|
||||||
MINIMAX_BASE_URL: ${MINIMAX_BASE_URL:-https://api.minimaxi.com}
|
|
||||||
JWT_SECRET: ${JWT_SECRET:-change_me_in_production}
|
JWT_SECRET: ${JWT_SECRET:-change_me_in_production}
|
||||||
|
INTERNAL_API_KEY: ${INTERNAL_API_KEY:-change_me_runtime_key}
|
||||||
STORAGE_DRIVER: ${STORAGE_DRIVER:-cos}
|
STORAGE_DRIVER: ${STORAGE_DRIVER:-cos}
|
||||||
STORAGE_COS_SECRET_ID: ${STORAGE_COS_SECRET_ID:-}
|
STORAGE_COS_SECRET_ID: ${STORAGE_COS_SECRET_ID:-}
|
||||||
STORAGE_COS_SECRET_KEY: ${STORAGE_COS_SECRET_KEY:-}
|
STORAGE_COS_SECRET_KEY: ${STORAGE_COS_SECRET_KEY:-}
|
||||||
@ -121,7 +157,53 @@ services:
|
|||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
networks:
|
networks:
|
||||||
- zhixi-net
|
- zhixi-net
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '1'
|
||||||
|
memory: 512M
|
||||||
|
reservations:
|
||||||
|
cpus: '0.25'
|
||||||
|
memory: 128M
|
||||||
|
|
||||||
|
# ── Heavy Runtime (Rust AI Worker) ──
|
||||||
|
heavy-runtime:
|
||||||
|
build:
|
||||||
|
context: ../zhixi-heavy-runtime
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
image: zhixi-heavy-runtime:latest
|
||||||
|
container_name: zhixi-heavy-runtime
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
RUST_LOG: ${RUNTIME_LOG_LEVEL:-info}
|
||||||
|
RUNTIME_INSTANCE_ID: heavy-runtime-1
|
||||||
|
API_INTERNAL_BASE_URL: http://api:3000
|
||||||
|
RUNTIME_SERVICE_TOKEN: ${INTERNAL_API_KEY:-change_me_runtime_key}
|
||||||
|
DEEPSEEK_API_KEY: ${DEEPSEEK_API_KEY:-}
|
||||||
|
MAX_CONCURRENCY: '4'
|
||||||
|
POLL_INTERVAL_MS: '5000'
|
||||||
|
JOB_TIMEOUT_SECONDS: '120'
|
||||||
|
HTTP_TIMEOUT_SECONDS: '30'
|
||||||
|
depends_on:
|
||||||
|
- api
|
||||||
|
healthcheck:
|
||||||
|
test: ['CMD', 'wget', '-qO-', 'http://localhost:8080/health']
|
||||||
|
interval: 30s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 3
|
||||||
|
start_period: 10s
|
||||||
|
networks:
|
||||||
|
- zhixi-net
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '2'
|
||||||
|
memory: 1G
|
||||||
|
reservations:
|
||||||
|
cpus: '0.5'
|
||||||
|
memory: 256M
|
||||||
|
|
||||||
|
# ── NGINX ──
|
||||||
nginx:
|
nginx:
|
||||||
image: nginx:1.25-alpine
|
image: nginx:1.25-alpine
|
||||||
container_name: zhixi-nginx
|
container_name: zhixi-nginx
|
||||||
@ -134,8 +216,21 @@ services:
|
|||||||
- ./nginx/conf.d:/etc/nginx/conf.d:ro
|
- ./nginx/conf.d:/etc/nginx/conf.d:ro
|
||||||
depends_on:
|
depends_on:
|
||||||
- api
|
- api
|
||||||
|
healthcheck:
|
||||||
|
test: ['CMD', 'wget', '-qO-', 'http://localhost/health']
|
||||||
|
interval: 15s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 3
|
||||||
networks:
|
networks:
|
||||||
- zhixi-net
|
- zhixi-net
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '0.5'
|
||||||
|
memory: 128M
|
||||||
|
reservations:
|
||||||
|
cpus: '0.1'
|
||||||
|
memory: 32M
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
mysql_data:
|
mysql_data:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user