部署 / 闯关模式

Docker Compose 跑完整后端服务

把 FastAPI、PostgreSQL、Redis 放进同一张启动清单,一条命令跑完整环境。

一句话:Docker Compose 可以把 FastAPI、PostgreSQL、Redis 这些服务放进同一张启动清单里,一条命令跑完整后端环境。

本篇学完你会什么:能写一个基础 docker-compose.yml,让 API、数据库、Redis 一起启动,并知道怎么查日志和排错。

1. 为什么需要 Compose

一个真实后端常常不只一个进程:

  • FastAPI
  • PostgreSQL
  • Redis
  • 以后可能还有 Nginx、Celery worker

一个个 docker run 会很乱。Compose 就像启动总清单。

Docker Compose 后端服务栈

2. 完整后端服务包含什么

最小组合:

api      FastAPI 服务
db       PostgreSQL 数据库
redis    缓存和限流

访问关系:

api -> db
api -> redis

在 Compose 网络里,服务之间用服务名访问。

3. 项目结构

demo-api/
  app/
    main.py
  requirements.txt
  Dockerfile
  docker-compose.yml
  .env

4. Dockerfile

FROM python:3.12-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

关键点:

  • 先复制 requirements.txt,利用 Docker 缓存。
  • 再复制代码。
  • 容器里监听 0.0.0.0,外部才能访问。

5. docker-compose.yml

services:
  api:
    build: .
    ports:
      - "8000:8000"
    env_file:
      - .env
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started

  db:
    image: postgres:16
    environment:
      POSTGRES_USER: demo
      POSTGRES_PASSWORD: demo
      POSTGRES_DB: demo
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U demo -d demo"]
      interval: 5s
      timeout: 3s
      retries: 10

  redis:
    image: redis:7
    ports:
      - "6379:6379"

volumes:
  postgres_data:

6. 环境变量

.env

DATABASE_URL=postgresql+asyncpg://demo:demo@db:5432/demo
REDIS_URL=redis://redis:6379/0
JWT_SECRET=change-me-in-production

注意:

  • 容器里访问数据库地址是 db,不是 localhost
  • 容器里访问 Redis 地址是 redis

7. 启动和停止

启动:

docker compose up -d --build

看状态:

docker compose ps

看日志:

docker compose logs -f api

停止:

docker compose down

停止并删除数据库数据:

docker compose down -v

这个命令会删数据,执行前要确认。

8. 健康检查

FastAPI 建议提供:

@app.get("/health")
async def health():
    return {"status": "ok"}

启动后访问:

http://localhost:8000/health

如果数据库迁移也要自动执行,可以在启动命令里加:

CMD ["sh", "-c", "alembic upgrade head && uvicorn app.main:app --host 0.0.0.0 --port 8000"]

9. 常见错误

问题原因解决
API 连不上数据库用了 localhostCompose 内用 db
数据库重启后数据丢没挂 volume配置 postgres_data
端口被占用本机已有服务改左边端口
API 先于数据库启动没健康检查depends_on 配 healthcheck
改代码没生效镜像没重建docker compose up -d --build

10. 上线前检查

[ ] .env 不提交真实密码
[ ] 数据库有 volume
[ ] API 有 /health
[ ] 服务之间用服务名访问
[ ] JWT_SECRET 生产环境已替换
[ ] 迁移命令明确
[ ] 日志能查
[ ] 端口映射清楚

总结表

名词大白话
Compose多服务启动清单
service一个服务
volume数据保险柜
depends_on启动依赖
healthcheck健康检查
env_file环境变量文件

下一篇建议:大白话讲解——后端服务稳定性