Skip to content

课 1 · Docker Compose 完整部署

本课目标

把模块 1 的开发环境 Compose 升级为完整部署配置,覆盖启动顺序、依赖等待、健康检查和日志收集。

关键理解:开发环境 Compose 和部署 Compose 的核心区别是"谁等谁"——部署时必须等基础服务完全就绪才启动应用。

开发 vs 部署配置的区别

开发(模块 1)部署(本课)
启动顺序手动 pnpm dev:infradepends_on + condition: service_healthy
代码更新本机 tsx watch构建镜像
环境变量.env 本地文件Docker secrets 或环境变量
日志控制台输出集中到文件或日志服务

完整 Compose 配置

yaml
# infra/docker-compose.yml
version: '3.9'

services:
  redis:
    image: redis:7-alpine
    healthcheck:
      test: ['CMD', 'redis-cli', 'ping']
      interval: 5s
      timeout: 3s
      retries: 5
    volumes:
      - redis-data:/data

  elasticsearch:
    image: elasticsearch:8.13.0
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
      - ES_JAVA_OPTS=-Xms512m -Xmx512m
    healthcheck:
      test: ['CMD-SHELL', 'curl -sf http://localhost:9200/_cluster/health | grep -q yellow\\|green']
      interval: 10s
      timeout: 5s
      retries: 12
    volumes:
      - es-data:/usr/share/elasticsearch/data

  api:
    build:
      context: ..
      dockerfile: apps/api/Dockerfile
    ports:
      - '3000:3000'
    environment:
      - NODE_ENV=production
      - REDIS_URL=redis://redis:6379
      - ELASTICSEARCH_URL=http://elasticsearch:9200
    depends_on:
      redis:
        condition: service_healthy
      elasticsearch:
        condition: service_healthy
    healthcheck:
      test: ['CMD-SHELL', 'curl -sf http://localhost:3000/health']
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  worker:
    build:
      context: ..
      dockerfile: apps/worker/Dockerfile
    environment:
      - NODE_ENV=production
      - REDIS_URL=redis://redis:6379
      - ELASTICSEARCH_URL=http://elasticsearch:9200
    depends_on:
      api:
        condition: service_healthy  # Worker 等 API 和基础设施都就绪
    restart: unless-stopped

  web:
    build:
      context: ..
      dockerfile: apps/web/Dockerfile
    ports:
      - '8080:80'
    depends_on:
      api:
        condition: service_healthy

volumes:
  redis-data:
  es-data:

Dockerfile(API 示例)

dockerfile
# apps/api/Dockerfile
FROM node:20-alpine AS base
RUN corepack enable pnpm

FROM base AS deps
WORKDIR /app
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml ./
COPY apps/api/package.json ./apps/api/
COPY packages/ ./packages/
RUN pnpm install --frozen-lockfile

FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN pnpm --filter api build

FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/apps/api/dist ./dist
COPY --from=deps /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/index.js"]

启动顺序可视化

redis ──healthy──┐
                 ├──> api ──healthy──┬──> worker
elasticsearch ───┘                   └──> web

depends_on: condition: service_healthy 保证上游服务通过 healthcheck 才会启动下游服务,不靠"等几秒"来猜测。

常用部署命令

bash
# 构建并启动所有服务
docker compose up --build -d

# 查看服务状态
docker compose ps

# 查看某个服务的日志
docker compose logs -f api

# 停止所有服务
docker compose down

# 停止并删除数据卷(完全重置)
docker compose down -v

本节产物

infra/
  docker-compose.yml          # 完整部署配置(含健康检查和依赖)
apps/api/Dockerfile
apps/worker/Dockerfile
apps/web/Dockerfile

面试追问

你的项目如何控制成本?

三个方面:1)请求限流(模块 3),防止单用户或 Bug 导致大量 LLM 调用;2)问答缓存(模块 3),相同问题命中缓存不再调用模型;3)成本统计(模块 8 课 2),追踪每次调用的 token 数,及时发现异常消耗。部署阶段还会设置 LLM API 账户的每日消费限额,作为最后一道防线。

Docker Compose 和 Kubernetes 在什么情况下选哪个?

Docker Compose 适合:单机部署、开发环境、团队规模小、不需要自动扩缩容。Kubernetes 适合:多节点集群、需要自动扩缩容、高可用、有 DevOps 团队维护。进阶项目是单机课程项目,Docker Compose 已经足够,面试时说清楚选型理由即可。

面向前端工程师和独立开发者的 AI 应用工程课程