正在学习
7.5 使用 Claude 引导的 CI/CD 进行部署
系统设置
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1
WORKDIR /app
# 安装运行时依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 复制应用
COPY app.py .
# 暴露端口并启动
EXPOSE 8000
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "2"]
docker-compose.yml(可选的本地"类生产"运行)
version: "3.9"
services:
taskflow:
build: .
image: taskflow:local
ports:
- "8000:8000"
restart: unless-stopped
本地运行:
docker compose up --build
# 访问 http://localhost:8000/health
deploy.sh
此脚本在您的远程服务器上(或通过 SSH)运行,使用简单的容器拉取并重启服务。它是幂等的,可以安全地重新运行。
#!/usr/bin/env bash
# deploy.sh – 拉取并重启 TaskFlow 服务
# 用法(在远程主机上或通过 SSH):./deploy.sh <image_tag>
# 示例:./deploy.sh ghcr.io/your-org/taskflow:main-abc123
set -euo pipefail
IMAGE_TAG="${1:-}"
APP_NAME="taskflow"
PORT="${PORT:-8000}"
if [[ -z "$IMAGE_TAG" ]]; then
echo "用法:$0 <image_tag>"
exit 1
fi
echo "[deploy] 正在拉取 $IMAGE_TAG"
docker pull "$IMAGE_TAG"
# 创建一次网络;如果已存在则忽略
docker network create app_net >/dev/null 2>&1 || true
echo "[deploy] 正在停止旧容器(如果有)"
docker rm -f "$APP_NAME" >/dev/null 2>&1 || true
echo "[deploy] 正在启动新容器"
docker run -d \
--name "$APP_NAME" \
--restart unless-stopped \
--network app_net \
-p 8000:8000 \
"$IMAGE_TAG"
# 健康检查
echo "[deploy] 正在等待健康检查端点..."
for i in {1..20}; do
if curl -fsS "http://127.0.0.1:${PORT}/health" >/dev/null; then
echo "[deploy] 健康"
exit 0
fi
sleep 1
done
echo "[deploy] 健康检查失败;正在打印日志"
docker logs "$APP_NAME" || true
exit 1
在远程主机上使其可执行:
chmod +x deploy.sh
.github/workflows/ci.yml
此 GitHub Actions 工作流运行测试(如果存在),构建镜像并将其推送到 GitHub 容器注册表(GHCR),然后通过在您的服务器上调用 deploy.sh 来通过 SSH 进行部署。
name: ci-cd
on:
push:
branches: [ "main" ]
workflow_dispatch: {}
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}/taskflow
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- run: |
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# 如果存在则安装测试依赖
pip install pytest || true
# 如果存在测试则运行
if ls -1 test*.py tests 2>/dev/null; then
pytest -q
else
echo "未找到测试;跳过。"
fi
build-and-push:
needs: test
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: 登录 GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: 提取短 SHA
id: vars
run: echo "SHORT_SHA=GITHUB_OUTPUT
- name: 构建并推送
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: |
{{ env.IMAGE_NAME }}:latest
{{ env.IMAGE_NAME }}:main-${{ steps.vars.outputs.SHORT_SHA }}
deploy:
needs: build-and-push
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: 准备镜像标签
id: vars
run: echo "IMAGE={{ env.IMAGE_NAME }}:main-GITHUB_OUTPUT
- name: 通过 SSH 部署
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.DEPLOY_HOST }}
username: ${{ secrets.DEPLOY_USER }}
key: ${{ secrets.DEPLOY_KEY }}
script: |
set -e
cd ${{ secrets.DEPLOY_PATH }}
./deploy.sh "${{ steps.vars.outputs.IMAGE }}"
在您的仓库设置中需要配置的密钥
- DEPLOY_HOST – 您服务器的主机名或 IP
- DEPLOY_USER – 具有 Docker 权限的 SSH 用户
- DEPLOY_KEY – 该用户的私钥(对仓库为只读)
- DEPLOY_PATH – 服务器上包含 deploy.sh 的目录
远程主机一次性设置
- 安装 Docker。
- 将 deploy.sh 复制到 ${DEPLOY_PATH} 并使其可执行。
- 确保 SSH 用户可以运行 Docker(例如,添加到 docker 组)。
本地试运行
您可以在本地模拟构建步骤:
docker build -t taskflow:dev .
docker run -p 8000:8000 --rm taskflow:dev
#
澄清表
| 阶段 | 发生事项 | Claude 的贡献 | 结果 |
| --- | --- | --- | --- |
| 测试 | 安装依赖,如果存在测试则运行 pytest | 强化断言、补充缺失的测试、解释失败原因 | 失败的代码绝不会发布 |
| 构建 | 从 Dockerfile 构建容器镜像 | 建议使用更精简的基础镜像、多阶段构建、健康检查端点 | 可复现的运行时环境 |
| 推送 | 打标签并发布到镜像仓库 | 强制使用语义化标签,生成发布说明 | 确定性的制品 |
| 部署 | 远程脚本拉取标签并重启容器 | 提出安全回退、健康检查、回滚命令 | 可预测的发布过程 |
| 观察 | 健康探针和日志 | 总结日志,提出告警和指标建议 | 更快的故障响应 |
现在你拥有了一条清晰的 CI/CD 路径,团队中的任何人都可以一目了然。测试把关变更,容器保证一致的运行时,而一个简洁的部署脚本通过健康检查提供安全、幂等的发布。Claude 的作用是让这个循环保持紧凑:将差异总结为发布说明,提出更安全的部署逻辑,并在功能变更时生成测试。在下一节中,你将使用可配置的环境(开发、预发布和生产)来扩展这个部署方案,由 Claude 帮助你管理密钥、配置漂移和晋升策略。
## 7.6 经验教训与改进
每一条部署流水线都有其自身的教训。通过 Claude 引导的 CI/CD 搭建过程,展示了当自动化与推理智能相结合时,自动化将变得多么强大。本节将回顾哪些做法有效、哪些可以改进,以及如何让 Claude 作为始终在场的开发伙伴,持续演进你的构建–测试–部署循环。目标不仅仅是拥有一个可用的流水线,而是一个自文档化、可靠且适应性强的流水线——这些特质正是 Claude 能够独特强化的。
**概念发展**
你在上一节中构建的 CI/CD 流水线遵循现代 DevOps 原则:自动化一切可能静默失败的事项。每一个自动化步骤——测试、容器化、部署——都是对人为错误的防御。然而,将 Claude 集成到这一循环中,使其超越了机械化流程。Claude 带来了认知自动化:推理变更、检测模式,并在故障到达生产环境之前提出改进建议的能力。
这些经验可以围绕四个成熟度支柱加以总结:
1. **一致性优于速度**:如果产出的结果不一致,再快的流水线也毫无价值。Claude 有助于维护命名规范、同步 Docker 标签,并在各环境间强制执行编码标准。
2. **测试深度至关重要**:单元测试是好的,语义化测试更佳。Claude 可以分析 API 模式,提出基于属性的测试,并解释业务逻辑与规范之间的差距。
3. **部署应当可观测**:健康检查和日志收集必须嵌入每一次发布中。Claude 能够解析你的部署日志,识别那些人类可能忽略的、非致命但关键的模式(例如启动缓慢或警告信息)。
4. **迭代永无止境**:每一条流水线都是一个活的系统。Claude 总结差异并生成改进建议的能力,使持续优化变得自然而不繁重。
**动手实践:使用 Claude 提出流水线改进建议**
在 TaskFlow API 多次成功部署之后,假设你的日志开始显示由于依赖膨胀导致的较长启动时间。你可以直接提示 Claude 来帮助改进这个流水线步骤。
**提示示例**
"Claude,我们的 Docker 构建步骤耗时超过两分钟,镜像大小已超过 1GB。请分析此 Dockerfile,并就构建速度和镜像大小提出优化建议。"
Claude 可能会以结构化且具备上下文感知的方式回应,例如:
- 将 `python:3.11-slim` 替换为多阶段构建,在一个层中编译依赖,并将仅运行时所需的文件复制到最终镜像。
- 使用 `pip install --no-cache-dir` 配合固定的 `requirements.txt` 以减少重建时间。
- 引入 `.dockerignore` 文件以排除不必要的文件,例如 `.git`、测试和本地缓存。
以下改进后的 Dockerfile 整合了这些变更:
```dockerfile
练习题
在 Dockerfile 中设置 ENV PYTHONDONTWRITEBYTECODE=1 的目的是什么?
A. 禁用 Python 字节码生成
B. 启用 Python 字节码生成
C. 优化 Python 性能
D. 设置 Python 版本
哪个命令用于在Dockerfile中暴露8000端口?
A.
EXPOSE 8000B.
PORT 8000C.
OPEN 8000D.
LISTEN 8000deploy.sh 脚本中包含哪些用于重启 TaskFlow 服务的步骤?(选择所有适用的)
A. 拉取最新的镜像
B. 创建 Docker 网络
C. 运行数据库迁移
D. 移除旧容器
E. 启动新容器
docker compose up --build 命令用于在本地构建和运行 Docker Compose 配置。
在远程主机上使 deploy.sh 脚本可执行的命令是 ___。
deploy.sh 脚本中健康检查的目的是什么?
哪个 GitHub Actions 工作流作业负责构建 Docker 镜像并将其推送到 GHCR?
A.
testB.
build-and-pushC.
deployD.
ci-cd哪个文件是 Dockerized FastAPI + GitHub Actions + SSH Deploy 示例所必需的?(选择所有适用的)
A.
app.pyB.
requirements.txtC.
DockerfileD.
deploy.shE.
.github/workflows/ci.ymlDockerfile 中的 WORKDIR /app 命令将容器内的工作目录设置为 /app。
在 GitHub Actions 工作流程中运行测试的命令是 ___。
在 Docker 设置中,requirements.txt 文件的作用是什么?
在 deploy.sh 脚本中,哪个命令用于启动 TaskFlow 服务?
A.
docker start taskflowB.
docker run -d --name taskflow ...C.
docker compose upD.
docker exec taskflow在部署过程中,GitHub Actions 工作流执行了哪些步骤?(选择所有适用的项)
A. 运行测试
B. 构建并推送 Docker 镜像
C. 通过 SSH 部署
D. 安装 Python 依赖
E. 创建 Docker 网络
Dockerfile 中的 COPY app.py . 命令将 app.py 文件从主机复制到容器的工作目录。
GitHub Actions 工作流中登录 GHCR 的命令是 ___。
Dockerfile中EXPOSE 8000命令的目的是什么?
哪个命令用于在本地模拟构建步骤?
A.
docker build -t taskflow:dev .B.
docker compose up --buildC.
docker run -p 8000:8000 --rm taskflow:devD.
docker pull taskflow:dev以下哪些是 GitHub Actions 工作流所需的存储库密钥?(选择所有适用的)
A.
DEPLOY_HOSTB.
DEPLOY_USERC.
DEPLOY_KEYD.
DEPLOY_PATHE.
GITHUB_TOKEN在 Dockerfile 中,EXPOSE 8000 指令的作用是什么,它与 API 测试概念有何关联?
A. 它指定了应用程序内部监听的端口,API 测试应验证该端口上的响应
B. 它定义了 SSH 访问的端口,与 API 测试无关
C. 它设置了 Docker 网络的默认端口,但 API 测试应使用随机端口
D. 它只是一个文档提示,对容器行为或测试没有影响
CI/CD 流水线 (ci.yml) 中的哪些步骤确保了确定性部署,它们与 FastAPI 测试实践有何关联?
A. 运行单元测试的 'test' 作业
B. 将服务打包到容器中的 'build-and-push' 作业
C. 提取短 SHA 用于镜像标记的步骤
D. 将精确的镜像拉取到目标的 'deploy' 作业
E. 在测试环境中安装 pytest 的步骤
deploy.sh 中的健康检查(对 /health 端点的 curl 请求)验证了 API 在正常条件下是"可证明正确的",这符合先验知识点 kp_7_4_001 中描述的要求。
Dockerfile 中的 _______ 指令将应用程序文件复制到容器中,这是 _______ 测试针对运行中的服务执行的前提条件。
解释 CI/CD 流水线的 'build-and-push' 作业 (ci.yml) 如何支持 API 测试的一致运行时环境原则。
登录后解锁笔记、知识点解析、AI 问答
立即登录