一条命令跑通整个后端:Docker Compose 入门

「从零到 AI 应用工程师」专栏 · 第 7 篇


到上一篇,你的对话服务已经有了:接口、分层、统一错误、PostgreSQL 历史、Redis 缓存。

但「在我电脑上能跑」和「别人(或未来的你)十分钟能跑」之间,还差一口气。本机装数据库、改端口、环境不一致......这些摩擦会吃掉大量热情。

今天把它们收成一句:

bash 复制代码
docker compose up -d --build

应用、Postgres、Redis 一起起来;再用 /healthz 证明依赖真的可用------不只是容器显示 Up。


一、先把三个词分清

概念 一句话
镜像 Image 只读的构建产物,像安装包
容器 Container 镜像跑起来的进程实例
Compose 用一份 YAML 声明「多容器怎么一起跑」

Compose 里,服务名就是容器网络里的主机名 。所以应用连数据库应写 db,连 Redis 应写 redis------不要写 127.0.0.1

127.0.0.1 在容器里指的是这个容器自己,不是你的笔记本电脑,也不是旁边的数据库容器。这是新手踩得最多的坑。


二、最小 Dockerfile

dockerfile 复制代码
FROM python:3.11-slim

ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /app

# 先装依赖,再拷代码 ------ 利用层缓存,改代码不必每次重装包
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

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

两个细节:

  • 监听 0.0.0.0,否则容器外访问不到;
  • requirements.txt 与源码分开 COPY,改一行业务代码不会让依赖层全部失效。

三、docker-compose.yml(应用 + 库 + 缓存)

yaml 复制代码
services:
  db:
    image: postgres:16
    environment:
      POSTGRES_USER: app_user
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: chat_db
    volumes:
      - pg_data:/var/lib/postgresql/data
      - ./sql/init.sql:/docker-entrypoint-initdb.d/01_init.sql:ro
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app_user -d chat_db"]
      interval: 5s
      timeout: 5s
      retries: 10

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

  web:
    build: .
    env_file: .env.docker
    ports:
      - "127.0.0.1:8000:8000"   # 只绑本机,降低误暴露风险
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "python -c \"import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/healthz')\"",
        ]
      interval: 10s
      timeout: 5s
      retries: 10

volumes:
  pg_data:
  redis_data:

.env.docker 示例(不要提交真实密钥):

env 复制代码
DB_HOST=db
DB_PORT=5432
DB_USER=app_user
DB_PASSWORD=请换成强密码
DB_NAME=chat_db

REDIS_HOST=redis
REDIS_PORT=6379

API_TOKEN=请换成你的令牌
MODEL_API_KEY=sk-你的密钥
MODEL_API_URL=https://api.example.com/v1/chat/completions
MODEL_NAME=your-model-name

应用代码里读库、读缓存,主机名要用环境变量里的 db / redis


四、健康检查:Up 不等于可用

depends_on: condition: service_healthy 比「只等容器启动」强一截,但应用自己仍应提供:

text 复制代码
GET /ping     → 进程活着
GET /healthz  → 进程 + 数据库 + Redis(必要时再加模型配置检查)

示例逻辑:

python 复制代码
@router.get("/healthz")
async def healthz():
    db_ok = check_db()       # SELECT 1
    redis_ok = check_redis() # PING
    ready = db_ok and redis_ok
    status_code = 200 if ready else 503
    return JSONResponse(
        status_code=status_code,
        content={
            "code": status_code,
            "message": "ok" if ready else "dependency not ready",
            "data": {"db": db_ok, "redis": redis_ok},
        },
    )

验收时:容器 Up 只是起点,/healthz 返回 200 才算栈就绪。


五、常用命令

bash 复制代码
# 构建并后台启动
docker compose up -d --build

# 看状态
docker compose ps

# 看日志(出问题先看这里)
docker compose logs --tail=100 web
docker compose logs --tail=100 db

# 停掉(默认保留数据卷)
docker compose down

# 停掉并删除数据卷 ------ 危险,本地数据会没
# docker compose down -v

改了 .env 或依赖:通常需要 重建容器 ,不是简单 restart

bash 复制代码
docker compose up -d --build --force-recreate web

六、验收清单

bash 复制代码
docker compose up -d --build
docker compose ps

curl -i http://127.0.0.1:8000/ping
curl -i http://127.0.0.1:8000/healthz

curl -X POST http://127.0.0.1:8000/chat \
  -H "Authorization: Bearer 你的令牌" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "docker_demo",
    "session_id": "session_docker_01",
    "message": "栈是否健康"
  }'

全部通过,阶段 1 的「能交付最小后端」就齐了。


七、常见坑(建议贴显示器旁)

  1. 容器里把数据库地址写成 localhost → 改成服务名 db
  2. 密码、Token、模型 Key 写进镜像或打进 Git。 → 环境变量 / env_file,示例用 .env.example
  3. 以为 depends_on 等于数据库已可查询。 → 加 healthcheck;应用再做 /healthz
  4. 误用 docker compose down -v → 本地库被清空。
  5. 改了 init.sql 却不见生效。 → 初始化脚本只在数据卷首次创建时跑;已有卷需要迁移或删卷重建(删卷会丢数据)。
  6. 生产把 5432 / 6379 映射到公网。 → 数据库和缓存只走内部网络;本示例仅把 8000 绑在 127.0.0.1
  7. 改了依赖不 --build → 容器里仍是旧包。

八、阶段 1 小结:你现在手里有什么

从第 2 篇到第 7 篇,一条对话后端的骨架已经立住:

能力
02 FastAPI + 大模型,打通 /chat
03 路由 / 业务 / 客户端分层
04 统一响应、统一异常、request_id
05 PostgreSQL 历史 + 分页
06 Redis 缓存重复问题(可降级)
07 Docker Compose 一键拉起整栈

这不是玩具脚本了------这是后面做 RAG、做 Agent 时,可以继续往上长的底座。


九、带走这三条

  1. Compose 把应用、依赖、网络、卷、健康检查变成可重复执行的声明。
  2. 容器网络用服务名;持久数据用 Volume;密钥用环境注入。
  3. 验收看 /healthz 和核心接口,不只看容器 Up。

下一阶段进入专栏最硬核的一块:RAG------让大模型读懂你自己的资料,还不许瞎编。 第 8 篇先把概念和全貌讲清,再进入解析、分块、向量检索。

这是专栏第 7 篇,也是 chat-api 阶段的收官。两天一更,RAG 见。

相关推荐
十三画者2 小时前
【文献分享】3d-OT:面向空间多组学异质性切片对齐的深度几何感知框架
人工智能·机器学习·数据挖掘·数据分析
八号当铺2 小时前
我做了一个多端基金收益助手:从养基宝数据到 Web、桌面端、浏览器插件和 IDE 插件
前端·人工智能·github
mqiqe2 小时前
构建企业级 AI 原生架构:LLM Gateway、RAG、Agent 与 MCP 的协同关系解析
人工智能·架构·gateway
qq_425516182 小时前
录音转文字工具免费下载:免费额度与功能限制对比
android·人工智能·智能手机·powerpoint
智体工坊2 小时前
从零搭建 AI 模型中转网关:部署、渠道、定价、装修全记录
运维·服务器·人工智能·搜索引擎·自动化
gnsnswa2 小时前
解读6大AI人工智能认证证书
人工智能·信息可视化·职场和发展·数据分析·aigc·学习方法·信息与通信
明如正午2 小时前
codebuddy-ignore-详解
人工智能·codebuddy
Canace2 小时前
GPT-5.6 到底怎么选?一文搞懂 Sol、Terra、Luna 和 Ultra
前端·人工智能·chatgpt
anxiao_m2 小时前
2026教学AI云桌面横向测评!五大主流品牌实景能力对比
大数据·人工智能·机器学习