零基础入门python70:Docker Compose 编排完整后端

零基础入门python70:Docker Compose 编排完整后端

上一篇课后练习讲解

Dockerfile 使用 Python 3.11 slim、固定依赖和非 root 用户;健康检查验证的是正在运行的应用,不是"build 成功"。

上一篇课后练习完整答案

上一篇练习已经落实到完整文件,运行下面代码可以观察本篇要求的成功和失败状态;数据库写入全部放在明确事务边界内。

答案要点:Dockerfile 分层安装依赖、复制 app、非 root 运行 Uvicorn;docker history 检查镜像不含 .env 和密钥。

完整答案文件:Dockerfile

完整参考答案文件

完整文件:Dockerfile

dockerfile 复制代码
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app ./app
USER nobody
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

验收:运行项目测试(FastAPI/Flask 使用 python -m pytest -q,Django 使用 python manage.py test),再按本文 curl 或 Docker 命令检查预期状态码。

先复制 requirements 可利用依赖缓存;生产镜像不包含 .env、测试数据库和 Git;非 root 用户降低进程被利用后的权限。生产不使用 --reload。

一、Compose 服务边界

yaml 复制代码
services:
  api:
    build: .
    env_file: .env
    ports: ["8000:8000"]
    depends_on:
      postgres: {condition: service_healthy}
      redis: {condition: service_healthy}
  postgres:
    image: postgres:16
    environment:
      POSTGRES_DB: blog
      POSTGRES_USER: blog
      POSTGRES_PASSWORD: change-me
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U blog -d blog"]
  redis:
    image: redis:7-alpine
    healthcheck:
      test: ["CMD", "redis-cli", "PING"]

二、实际验收

powershell 复制代码
docker compose config
docker compose up -d --pull never
docker compose ps
docker compose exec redis redis-cli PING

确认 PostgreSQL healthy、Redis 返回 PONG、API 健康检查 200。停止 Redis 时公开列表仍可从数据库读取;停止 PostgreSQL 时 API 返回可诊断的 503,而不是无限等待。

课后练习

增加 MongoDB 和 migration 服务,写出镜像不存在、端口冲突和健康检查失败三种排错记录。下一篇配置 Nginx 和 HTTPS。

三、Compose 文件中的依赖关系

yaml 复制代码
services:
  api:
    build: .
    env_file: .env
    ports: ["8000:8000"]
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    restart: unless-stopped
  migrate:
    build: .
    command: alembic upgrade head
    env_file: .env
    depends_on:
      postgres:
        condition: service_healthy

depends_on 的健康条件只保证 Compose 在健康后启动容器,不能保证网络瞬间没有抖动;应用仍应在启动阶段重试数据库连接。迁移服务必须是一次性任务,不能让多个 API worker 同时执行 alembic upgrade。数据库凭据放 .env,不要写在镜像或 Compose 文件里。

四、卷、网络和停止顺序

PostgreSQL 使用命名卷 pgdata,Redis 可使用 redisdata 保存重启后的缓存(如果缓存可丢失也可以不挂卷)。docker compose down 不会删除卷,down -v 才会删除数据,执行前必须确认环境。停止时先让 API 停止接收新请求,再停止依赖,避免大量 503。

powershell 复制代码
docker compose config
docker compose up -d --pull never
docker compose ps
docker compose logs migrate
docker compose exec redis redis-cli PING

预期迁移日志显示 Running upgrade,Redis 返回 PONG,API /health 返回 200。service "api" depends on undefined service 是缩进或服务名拼写错误;端口冲突可把宿主端口改为 18000:8000,容器内部仍用 8000;镜像不存在时使用本地 tag 或先构建,不能把 --pull never 的失败伪装成服务已启动。

五、本篇练习

增加 MongoDB 服务和一个 mongo-init 一次性脚本,写健康检查失败、端口占用、数据库凭据错误三份排错记录。下一篇将把 Nginx 放到公网入口,解释 TLS 终止和反向代理头。

六、Compose 到生产的差别

开发 Compose 可以映射 PostgreSQL 端口便于调试,生产通常只把数据库放在内部网络,不暴露宿主端口。restart: unless-stopped 能处理偶发进程退出,却不能修复坏迁移;迁移 job 失败时 API 不应继续接收写请求。为每个服务设置 CPU/内存上限,避免日志或异常重试耗尽主机资源。

本篇结束:完整模块文件

本节不是代码片段,而是本篇结束时该模块的完整版本。请先备份旧文件,再整体替换;替换后重新运行本篇命令和测试。阅读时重点看本篇新增的函数、事务边界和错误处理,未涉及的代码先不要自行删减。

完整配置

yaml 复制代码
services:
  api:
    build: ./fastapi-blog
    ports: ["8000:8000"]
    depends_on: [db,redis]
  db:
    image: mysql:8.4
  redis:
    image: redis:7-alpine
相关推荐
宸津-代码粉碎机1 小时前
OpenAI 连夜迎战 Grok Bot 和 Muse:AI 智能体从 “会聊天” 到 “能办事”,现在入场还来得及吗
java·大数据·人工智能·分布式·python
Y3815326622 小时前
SERP API 计费口径:credits_charged、执行失败扣费与退款边界
python·搜索引擎
蒸鱼Yuzheng3 小时前
设备端性能工件可靠导出:断点续传、哈希、manifest 与失败恢复
android·自动化测试·python·adb·数据完整性
圆圆讲门店4 小时前
挑选同城获客服务机构时需要考量的核心因素都有哪些?
大数据·网络·人工智能·python
傻啦嘿哟4 小时前
Python的默认参数把我坑惨了,原来写[]和写None的区别这么大
开发语言·python·机器学习
微小冷4 小时前
Python凸优化cvxpy初步
python·机器人·凸优化·数学规划·cvxpy
在世修行5 小时前
干货:显式映射 vs 自动判据
python·插件
xzal125 小时前
Python之简单理解栈和队列
python
lupai5 小时前
维修保养记录精准版 API 对接实战指南
数据库·python
水水不水啊5 小时前
告别杂乱的调试窗口:我用 Python + WebView 写了一个现代化串口助手
python·测试工具·嵌入式·嵌入式开发·串口调试·串口助手