《Docker Compose + Dockerfile 完全解析:手把手教你部署 FastAPI + LangGraph 项目》

📅 2026/8/6 4:00:06
《Docker Compose + Dockerfile 完全解析:手把手教你部署 FastAPI + LangGraph 项目》
《Docker Compose Dockerfile 完全解析手把手教你部署 FastAPI LangGraph 项目》引言在现代后端开发中Docker 已经成为部署和运行应用的标配。但对于初学者来说一个包含数据库、缓存、监控、应用服务的完整docker-compose.yaml文件往往令人望而生畏。本文将从一个真实的生产级项目出发逐行解析docker-compose.yaml和Dockerfile涵盖PostgreSQL pgvector向量数据库ValkeyRedis 兼容缓存FastAPI LangGraph 应用Prometheus Grafana cAdvisor 监控栈读完本文你将彻底理解“一次构建多处运行”的容器化核心理念。一、docker-compose.yaml 顶层结构解析yamlversion: 3.8 services: # ... 各个服务定义 networks: monitoring: driver: bridge volumes: grafana-storage: postgres-data: valkey-data:字段含义version: 3.8Compose 文件格式版本支持 Docker Engine 19.03.0services:定义所有容器服务应用、数据库、监控等networks:创建自定义桥接网络monitoring让所有服务通过服务名互相通信volumes:声明 Docker 命名卷用于数据持久化容器删除后数据不丢失关键理解所有服务加入同一个monitoring网络后app容器可以通过主机名db直接访问数据库容器无需暴露端口到宿主机。二、数据库服务db—— PostgreSQL pgvectoryamldb: image: pgvector/pgvector:pg16 platform: linux/amd64 environment: - POSTGRES_DB${POSTGRES_DB} - POSTGRES_USER${POSTGRES_USER} - POSTGRES_PASSWORD${POSTGRES_PASSWORD} ports: - 5432:5432 volumes: - postgres-data:/var/lib/postgresql/data healthcheck: test: [CMD-SHELL, pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}] interval: 10s timeout: 5s retries: 5 restart: always networks: - monitoring逐字段解读image: pgvector/pgvector:pg16使用官方 pgvector 镜像基于 PostgreSQL 16内置向量相似度搜索插件适用于 AI 应用中的 Embedding 存储和检索。platform: linux/amd64强制指定平台避免在 ARM 架构如 M1/M2 Mac上运行时出现兼容性问题。environment:从宿主机的.env文件读取数据库名、用户名、密码保持敏感信息不入库。ports: 5432:5432映射端口到宿主机方便用psql或数据库 GUI 工具直接连接调试。volumes:挂载命名卷postgres-data到/var/lib/postgresql/data确保数据库文件持久化。healthcheck:每 10 秒执行pg_isready检查数据库是否就绪。app服务依赖此健康状态确保数据库启动后才启动应用。restart: always容器异常退出时自动重启。三、Valkey 缓存服务Redis 兼容yamlvalkey: image: valkey/valkey:8.1.6-alpine ports: - 6379:6379 volumes: - valkey-data:/data healthcheck: test: [CMD, valkey-cli, ping] interval: 10s timeout: 5s retries: 5 restart: always networks: - monitoringimage: valkey/valkey:8.1.6-alpineValkey 是 Redis 的开源替代品完全兼容 Redis 协议Alpine 版本体积小。healthcheck通过valkey-cli ping检测服务是否正常。注意缓存是可选的。如果.env中未设置VALKEY_HOST应用不会启用缓存功能。四、应用服务app—— 核心业务yamlapp: build: context: . args: APP_ENV: ${APP_ENV:-development} ports: - 8000:8000 volumes: - ./app:/app/app - ./logs:/app/logs env_file: - .env.${APP_ENV:-development} environment: - APP_ENV${APP_ENV:-development} - JWT_SECRET_KEY${JWT_SECRET_KEY:-supersecretkeythatshouldbechangedforproduction} depends_on: db: condition: service_healthy healthcheck: test: [CMD, curl, -f, http://localhost:8000/health] interval: 30s timeout: 10s retries: 3 start_period: 10s restart: on-failure networks: - monitoring重点解析build:使用当前目录.作为构建上下文构建时传入APP_ENV构建参数默认development。volumes:./app:/app/app将本地代码挂载进容器覆盖镜像内的代码。修改本地代码后容器自动同步实现开发热重载。./logs:/app/logs将日志挂载到宿主机便于持久化查看。env_file:根据APP_ENV加载对应的.env.development或.env.production文件。environment:直接设置环境变量优先级高于env_file。JWT_SECRET_KEY提供了不安全默认值生产环境务必覆盖。depends_on:db服务必须处于service_healthy状态后才启动本容器避免启动时连接数据库失败。restart: on-failure仅在非正常退出时重启避免手动停止后反复重启。五、监控三件套Prometheus Grafana cAdvisor5.1 Prometheus —— 指标采集yamlprometheus: image: prom/prometheus:latest ports: - 9090:9090 volumes: - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml command: - --config.file/etc/prometheus/prometheus.yml networks: - monitoring restart: always挂载本地的prometheus.yml配置文件定义抓取目标如app:8000/metrics、cadvisor:8080/metrics。5.2 Grafana —— 可视化面板yamlgrafana: image: grafana/grafana:latest ports: - 3000:3000 volumes: - grafana-storage:/var/lib/grafana - ./grafana/dashboards:/etc/grafana/provisioning/dashboards - ./grafana/dashboards/dashboards.yml:/etc/grafana/provisioning/dashboards/dashboards.yml environment: - GF_SECURITY_ADMIN_PASSWORDadmin - GF_USERS_ALLOW_SIGN_UPfalse networks: - monitoring restart: always使用命名卷grafana-storage保存用户配置和面板数据。通过 Provisioning 方式自动加载预定义的仪表板JSON 文件。默认管理员密码admin生产环境务必修改。5.3 cAdvisor —— 容器资源监控yamlcadvisor: image: gcr.io/cadvisor/cadvisor:latest ports: - 8080:8080 volumes: - /:/rootfs:ro - /var/run:/var/run:rw - /sys:/sys:ro - /var/lib/docker/:/var/lib/docker:ro networks: - monitoring restart: always挂载宿主机的多个系统目录用于获取容器和宿主机的 CPU、内存、网络等运行时指标。六、Dockerfile 逐行解析dockerfileFROM python:3.13.2-slim WORKDIR /app使用 Python 3.13 的精简版镜像设置工作目录为/app。6.1 构建参数与环境变量dockerfileARG APP_ENVproduction ENV APP_ENV${APP_ENV} \ PYTHONFAULTHANDLER1 \ PYTHONUNBUFFERED1 \ PYTHONHASHSEEDrandom \ PIP_NO_CACHE_DIR1 \ PIP_DISABLE_PIP_VERSION_CHECKon \ PIP_DEFAULT_TIMEOUT100ARG APP_ENVproduction构建参数可通过docker build --build-arg APP_ENVdevelopment覆盖。ENV设置运行时环境变量优化 Python 和 pip 行为。6.2 安装系统依赖dockerfileRUN apt-get update apt-get install -y \ build-essential \ libpq-dev \ pip install --upgrade pip \ pip install uv \ rm -rf /var/lib/apt/lists/*build-essential提供 C/C 编译器用于编译某些 Python 原生扩展。libpq-devPostgreSQL 客户端开发库供psycopg2连接数据库使用。uv极快的 Python 包管理器替代 pip/poetry。rm -rf /var/lib/apt/lists/*清理 apt 缓存大幅减小镜像体积最佳实践。6.3 分层复制依赖利用 Docker 缓存加速dockerfileCOPY pyproject.toml uv.lock ./ RUN uv sync --frozen --no-install-project只复制依赖定义文件安装第三方库暂不安装项目本身。核心技巧只要pyproject.toml和uv.lock不变这一层就会命中 Docker 缓存。每次修改源码时不会重新下载和安装依赖构建速度极快。6.4 复制源码并安装项目dockerfileCOPY . . RUN uv sync --frozen复制全部源码再次运行uv sync此时利用缓存只链接项目自身的包。6.5 安全与非 root 用户dockerfileRUN chmod x /app/scripts/docker-entrypoint.sh RUN useradd -m appuser chown -R appuser:appuser /app USER appuser RUN mkdir -p /app/logs赋予入口脚本执行权限。创建普通用户appuser将/app目录所有权转交给该用户。切换到非 root 用户运行防止容器内以 root 执行带来的安全风险。6.6 启动命令dockerfileEXPOSE 8000 ENTRYPOINT [/app/scripts/docker-entrypoint.sh] CMD [/app/.venv/bin/uvicorn, app.main:app, --host, 0.0.0.0, --port, 8000]ENTRYPOINT固定入口点先执行脚本通常用于数据库迁移等待。CMD提供默认参数给 ENTRYPOINT最终启动 Uvicorn 服务器。七、Dockerfile 与 Compose 的协作“一次构建多处运行”组件职责Dockerfile构建镜像定义操作系统环境、依赖、源码和启动入口。它是“静态”的。docker-compose.yaml运行容器定义端口映射、卷挂载、环境变量注入、服务依赖。它是“动态”的。开发场景Compose 通过volumes: - ./app:/app/app挂载本地代码覆盖镜像内容配合APP_ENVdevelopment实现热重载调试。生产场景移除代码卷挂载传入APP_ENVproduction使用镜像内固化的稳定代码保证环境一致性。八、总结docker-compose.yaml定义了6 个服务应用、数据库、缓存、Prometheus、Grafana、cAdvisor构成了一个完整的可观测性闭环。Dockerfile通过分层构建、非 root 用户、依赖缓存等最佳实践打造了安全高效的镜像。两者结合实现了“一次构建镜像多处运行不同配置”的容器化黄金法则。