Web项目工程化规范 — 运维安全与文档¶
核心知识点速查表¶
| 知识点 | 说明 |
|---|---|
| 八、数据库备份 | 见对应章节 |
| 九、进程管理与监控 | 见对应章节 |
| 十、HTTPS 与域名 | 见对应章节 |
| 十一、安全加固 | 见对应章节 |
| 十二、文档 | 见对应章节 |
| 功能特性 | 见对应章节 |
| 快速开始 | 见对应章节 |
| 项目结构 | 见对应章节 |
八、数据库备份¶
为什么需要¶
不备份的后果:一行误操作的 SQL(DELETE FROM users——忘了 WHERE),所有用户数据永久丢失。
8.1 SQLite 备份策略 [必须]¶
#!/bin/bash
# /opt/t2d-api/scripts/backup_db.sh —— SQLite 数据库备份脚本
# === 配置 ===
DB_PATH="/opt/t2d-api/data.db" # 数据库文件路径
BACKUP_DIR="/opt/t2d-api/backups" # 本地备份目录
DATE=$(date +%Y%m%d_%H%M%S) # 时间戳(如 20260504_143000)
BACKUP_FILE="$BACKUP_DIR/data_${DATE}.db" # 备份文件名
# === 创建备份目录 ===
mkdir -p "$BACKUP_DIR" # -p: 目录已存在也不报错
# === 使用 SQLite 的 .backup 命令(不锁表、一致性有保障) ===
sqlite3 "$DB_PATH" ".backup '$BACKUP_FILE'" # 官方推荐的备份方式
# 不要用 cp 命令!正在写入时 cp 可能拿到损坏的文件
# === 压缩 ===
gzip "$BACKUP_FILE" # 压缩,节省空间
echo "[$(date)] 备份成功: ${BACKUP_FILE}.gz"
# === 删除 7 天前的旧备份 ===
find "$BACKUP_DIR" -name "*.gz" -mtime +7 -delete # 只保留 7 天
8.2 cron 定时任务 [必须]¶
# 编辑定时任务
crontab -e # 打开当前用户的 cron 编辑器
# 添加以下行(每天凌晨 3 点执行备份)
0 3 * * * /opt/t2d-api/scripts/backup_db.sh >> /opt/t2d-api/logs/backup.log 2>&1
# 分 时 日 月 周 命令
# 0 3 * * * = 每天 03:00
# >> 追加输出到日志文件
# 2>&1 把错误也输出到同一个文件
# 验证 cron 是否生效
crontab -l # 列出所有定时任务
8.3 备份到远程(异地容灾)[推荐]¶
# 方案 1:rsync 同步到远程服务器
rsync -avz /opt/t2d-api/backups/ user@backup-server:/backups/t2d-api/
# -a 归档模式 -v 详细输出 -z 压缩传输
# 方案 2:上传到对象存储(阿里云 OSS / 腾讯 COS)
# 安装阿里云 CLI
pip install oss2
# 在备份脚本最后添加上传命令:
# python /opt/t2d-api/scripts/upload_to_oss.py "$BACKUP_FILE.gz"
# 方案 3:rclone(通用云存储同步工具,支持几十种云服务)
rclone copy /opt/t2d-api/backups/ remote:t2d-backups/ --max-age 7d
九、进程管理与监控¶
为什么需要¶
不做进程管理的后果: - 服务器重启后你的 FastAPI 不会自动启动 - 进程崩溃了没人知道,直到用户找你 - 内存泄漏慢慢把服务器搞崩
9.1 systemd service 配置 [必须]¶
# /etc/systemd/system/t2d-api.service —— systemd 服务单元文件
[Unit]
Description=T2D API Service # 服务描述
After=network.target # 等网络就绪后再启动
[Service]
Type=notify # Gunicorn 支持 systemd 通知
User=www-data # 运行用户(不要用 root!)
Group=www-data # 运行用户组
WorkingDirectory=/opt/t2d-api # 工作目录
# 用 Gunicorn 启动 FastAPI(UvicornWorker 处理异步请求)
ExecStart=/opt/t2d-api/.venv/bin/gunicorn \
app.main:app \
--worker-class uvicorn.workers.UvicornWorker \
--workers 3 \
--bind unix:/opt/t2d-api/gunicorn.sock \
--access-logfile - \
--error-logfile - \
--max-requests 1000 \
--max-requests-jitter 50 \
--graceful-timeout 30
# --worker-class 使用 Uvicorn 异步 worker
# --workers 3 启动 3 个 worker 进程(2*CPU+1)
# --bind unix:... 用 Unix Socket 通信(比 TCP 快)
# --max-requests 处理 1000 个请求后重启 worker(防内存泄漏)
# --max-requests-jitter 随机偏移,防止所有 worker 同时重启
# --graceful-timeout 优雅关闭等待时间
# 优雅重载(发送 HUP 信号,不断连接)
ExecReload=/bin/kill -s HUP $MAINPID
# 自动重启配置
Restart=on-failure # 异常退出时自动重启
RestartSec=10 # 重启前等 10 秒
StartLimitBurst=5 # 最多连续重启 5 次
StartLimitIntervalSec=60 # 60 秒内
# 日志
StandardOutput=journal # 标准输出写入 systemd 日志
StandardError=journal # 错误输出也写入
# 安全加固
NoNewPrivileges=true # 禁止获取新特权
PrivateTmp=true # 使用独立的 /tmp
[Install]
WantedBy=multi-user.target # 开机自动启动
# 加载并启动服务
sudo systemctl daemon-reload # 重新加载 service 文件
sudo systemctl enable t2d-api # 设为开机自启
sudo systemctl start t2d-api # 启动服务
# 常用管理命令
sudo systemctl status t2d-api # 查看状态
sudo systemctl reload t2d-api # 优雅重载(不断线)
sudo systemctl restart t2d-api # 完全重启
sudo journalctl -u t2d-api -f # 实时查看日志(-f = follow)
sudo journalctl -u t2d-api --since today # 查看今天的日志
9.2 健康检查端点 [必须]¶
# app/api/health.py —— 健康检查接口
from fastapi import APIRouter
from datetime import datetime
router = APIRouter(tags=["健康检查"])
@router.get("/health")
async def health_check():
"""基础存活检查 —— 进程还活着吗"""
return {"status": "ok", "timestamp": datetime.now().isoformat()}
@router.get("/health/ready")
async def readiness_check():
"""就绪检查 —— 能正常处理请求吗(检查数据库等依赖)"""
checks = {}
try:
# 检查数据库连接
from app.core.database import engine
async with engine.connect() as conn:
await conn.execute("SELECT 1") # 最简单的数据库探活
checks["database"] = "ok"
except Exception as e:
checks["database"] = f"error: {e}"
return {"status": "unhealthy", "checks": checks}
return {"status": "healthy", "checks": checks}
9.3 外部监控 [推荐]¶
| 工具 | 费用 | 功能 |
|---|---|---|
| UptimeRobot | 免费 50 个监控 | 每 5 分钟检查一次,宕机发邮件/微信 |
| Better Uptime | 免费版可用 | 更好看的状态页 |
| 自建 cron 检查 | 免费 | curl 你的 /health 端点 |
在 UptimeRobot 中添加: - Monitor Type: HTTP(s) - URL: https://your-domain.com/health - Monitoring Interval: 5 minutes - Alert Contacts: 你的邮箱/Telegram
十、HTTPS 与域名¶
为什么需要¶
不用 HTTPS 的后果: - 用户密码明文传输,同一个 WiFi 的人都能截获 - 浏览器显示"不安全"大红警告——用户直接跑了 - 搜索引擎会降低你网站的排名
10.1 Nginx 反向代理配置 [必须]¶
# /etc/nginx/sites-available/t2d-api —— Nginx 配置
# 第一步:先配 HTTP(让 Certbot 能验证域名)
server {
listen 80; # 监听 80 端口
server_name your-domain.com; # 你的域名
# Certbot 域名验证用的路径
location /.well-known/acme-challenge/ {
root /var/www/certbot; # Certbot 验证文件存放目录
}
# 其他所有请求转发给 FastAPI
location / {
proxy_pass http://unix:/opt/t2d-api/gunicorn.sock; # Unix Socket
proxy_set_header Host $http_host; # 传递原始域名
proxy_set_header X-Real-IP $remote_addr; # 真实客户端 IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; # http 或 https
proxy_read_timeout 300s; # 长任务超时时间
}
}
# 启用站点配置
sudo ln -s /etc/nginx/sites-available/t2d-api /etc/nginx/sites-enabled/
sudo nginx -t # 测试配置语法是否正确
sudo systemctl reload nginx # 重新加载配置
10.2 Let's Encrypt (Certbot) 配置 HTTPS [必须]¶
# 安装 Certbot
sudo apt update
sudo snap install --classic certbot # 用 snap 安装(官方推荐)
sudo ln -s /snap/bin/certbot /usr/bin/certbot # 创建快捷命令
# 申请证书(Certbot 会自动修改 Nginx 配置)
sudo certbot --nginx -d your-domain.com # 自动配置 HTTPS
# Certbot 会:
# 1. 验证你对域名的控制权
# 2. 下载证书到 /etc/letsencrypt/live/your-domain.com/
# 3. 自动修改 Nginx 配置,添加 SSL 相关指令
# 4. 添加 HTTP→HTTPS 自动跳转
# 验证自动续期
sudo certbot renew --dry-run # 模拟续期(不真正执行)
# Let's Encrypt 证书有效期 90 天,Certbot 自动续期
Certbot 自动修改后的 Nginx 配置大致是:
# Certbot 自动添加的 HTTPS 配置(不需要手写)
server {
listen 443 ssl;
server_name your-domain.com;
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://unix:/opt/t2d-api/gunicorn.sock;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# HTTP 自动跳转到 HTTPS
server {
listen 80;
server_name your-domain.com;
return 301 https://$host$request_uri; # 永久重定向到 HTTPS
}
10.3 Cloudflare 配置(国内加速 + 防护)[推荐]¶
如果域名放在 Cloudflare: 1. 注册 Cloudflare → 添加你的域名 2. 修改域名 DNS 服务器为 Cloudflare 提供的 3. SSL/TLS 模式选 Full (Strict)(后端有证书时最安全) 4. 开启 "Always Use HTTPS" 5. 好处:CDN 加速、DDoS 防护、免费 SSL
十一、安全加固¶
为什么需要¶
不做安全加固的后果: - 服务器被黑客入侵当矿机 - 数据库被拖库,用户数据泄露 - SSH 被暴力破解(每天数千次尝试)
11.1 防火墙(UFW)[必须]¶
# 安装并配置 UFW(Uncomplicated Firewall)
sudo apt install ufw # Ubuntu 通常已预装
# 设置默认策略
sudo ufw default deny incoming # 默认拒绝所有入站连接
sudo ufw default allow outgoing # 允许所有出站连接
# 放行必要端口
sudo ufw allow 22/tcp # SSH(如果改了端口就改这里)
sudo ufw allow 80/tcp # HTTP
sudo ufw allow 443/tcp # HTTPS
# 启用防火墙
sudo ufw enable # 启用(会提示可能断开 SSH,确认即可)
sudo ufw status verbose # 查看规则
# 【更安全】限制 SSH 只允许特定 IP
sudo ufw delete allow 22/tcp # 先删掉通用规则
sudo ufw allow from 你的固定IP to any port 22 # 只允许你的 IP 连 SSH
11.2 SSH 安全加固 [必须]¶
# 编辑 SSH 配置
sudo nano /etc/ssh/sshd_config
# 以下是建议修改的配置项:
Port 2222 # 改掉默认 22 端口(减少扫描噪音)
PermitRootLogin no # 禁止 root 直接登录
PasswordAuthentication no # 禁用密码登录(只允许密钥)
PubkeyAuthentication yes # 启用公钥认证
MaxAuthTries 3 # 最多尝试 3 次
ClientAliveInterval 300 # 5 分钟无操作断开
ClientAliveCountMax 2 # 发 2 次心跳包无响应断开
# 重启 SSH 服务(先开另一个终端测试能否登录!)
sudo systemctl restart sshd
重要提醒:修改 SSH 配置前,一定要保持一个已连接的终端窗口。如果配置出错导致无法登录,你还能用这个窗口改回来。
11.3 Fail2Ban [推荐]¶
# 安装
sudo apt install fail2ban # 安装 fail2ban
# 创建本地配置(不要直接改 jail.conf)
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
# 编辑 jail.local,找到 [sshd] 段:
sudo nano /etc/fail2ban/jail.local
# /etc/fail2ban/jail.local 关键配置
[DEFAULT]
bantime = 86400 # 封禁 24 小时(秒)
findtime = 600 # 10 分钟内
maxretry = 5 # 失败 5 次就封
[sshd]
enabled = true # 启用 SSH 防护
port = 2222 # 你的 SSH 端口(如果改了的话)
banaction = ufw # 用 UFW 执行封禁(和防火墙联动)
logpath = /var/log/auth.log # SSH 日志路径
# 可选:保护 Nginx(防止恶意请求)
[nginx-http-auth]
enabled = true
# 启动并查看状态
sudo systemctl enable fail2ban # 开机自启
sudo systemctl start fail2ban
sudo fail2ban-client status sshd # 查看 SSH 防护状态
# 会显示被封的 IP 数量和列表
11.4 安全响应头 [推荐]¶
在 FastAPI 中添加安全头中间件:
# app/middleware/security.py —— 安全响应头中间件
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.requests import Request
from starlette.responses import Response
class SecurityHeadersMiddleware(BaseHTTPMiddleware):
"""给每个响应添加安全头"""
async def dispatch(self, request: Request, call_next):
response: Response = await call_next(request)
# 防止 MIME 类型嗅探攻击
response.headers["X-Content-Type-Options"] = "nosniff"
# 防止网页被嵌入 iframe(点击劫持防护)
response.headers["X-Frame-Options"] = "DENY"
# 控制 Referer 头泄露信息
response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin"
# 强制 HTTPS(开启后浏览器会记住,1年内都走 HTTPS)
response.headers["Strict-Transport-Security"] = (
"max-age=31536000; includeSubDomains"
)
# 禁用危险的浏览器功能
response.headers["Permissions-Policy"] = (
"camera=(), microphone=(), geolocation=()"
)
return response
# app/main.py 中注册中间件
from app.middleware.security import SecurityHeadersMiddleware
app.add_middleware(SecurityHeadersMiddleware)
11.5 自动安全更新 [推荐]¶
# 启用自动安全更新
sudo apt install unattended-upgrades # 安装自动更新工具
sudo dpkg-reconfigure unattended-upgrades # 交互式配置,选 Yes
# 检查是否开启
cat /etc/apt/apt.conf.d/20auto-upgrades
# 应该显示:
# APT::Periodic::Unattended-Upgrade "1";
十二、文档¶
为什么需要¶
不写文档的后果: - 三个月后你自己都忘了这个接口怎么用 - 新同事接手该项目,看不懂就从头写 - API 没有文档,前端同事天天找你问参数格式
12.1 README 规范 [必须]¶
一个好的 README 至少包含:
# T2D-API:2型糖尿病肠道菌群分析平台
> 基于 FastAPI 的宏基因组分析数据服务化平台
## 功能特性
- 物种丰度查询与可视化
- 样本上传与自动分析
- 多样性指数计算
## 快速开始
### 环境要求
- Python 3.12+
- SQLite 3.x
### 安装与运行
```bash
git clone git@github.com:xxx/t2d-api.git
cd t2d-api
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # 编辑 .env 填入配置
uvicorn app.main:app --reload
API 文档¶
启动后访问:http://localhost:8000/docs
项目结构¶
app/
├── main.py # 应用入口
├── api/ # 路由
├── services/ # 业务逻辑
├── models/ # 数据模型
├── schemas/ # 请求/响应模型
└── core/ # 配置、数据库
部署¶
详见 部署文档
许可证¶
MIT License
### 12.2 API 文档(FastAPI 自带)[必须]
FastAPI 的杀手级特性:**自动生成交互式 API 文档**。
```python
# 只要在代码里写好类型标注和描述,文档自动生成
from fastapi import FastAPI, Query
app = FastAPI(
title="T2D-API", # 文档页标题
description="2型糖尿病肠道菌群分析平台", # 描述
version="1.0.0", # 版本号
)
@app.get(
"/api/v1/species",
summary="查询物种列表", # 接口概要
description="支持按名称模糊搜索和分页", # 详细描述
)
async def list_species(
keyword: str = Query( # Query 参数
default=None,
description="物种名称关键词(支持模糊搜索)",
examples=["Bacteroides"], # 示例值
),
page: int = Query(default=1, ge=1, description="页码"),
size: int = Query(default=20, ge=1, le=100, description="每页数量"),
):
...
访问两个自动生成的文档页面: - Swagger UI:http://localhost:8000/docs(交互式,能直接测试接口) - ReDoc:http://localhost:8000/redoc(更好看的只读文档)
12.3 CHANGELOG [推荐]¶
# 用 commitizen 自动从提交记录生成 CHANGELOG
cz changelog # 自动生成 CHANGELOG.md
# 原理:根据 feat/fix/refactor 等类型的提交信息,自动分类整理
生成的 CHANGELOG.md 大致长这样:
## 1.1.0 (2026-05-04)
### Features
- 新增物种丰度查询接口 (#12)
- 支持批量样本上传 (#15)
### Bug Fixes
- 修复大文件上传超时问题 (#13)
- 修复分页查询总数不准的问题 (#14)
十三、依赖管理¶
为什么需要¶
不管理依赖的后果: - "我电脑上能跑,服务器上跑不了"——版本不一致 - 某个依赖有安全漏洞——你完全不知道 - pip install xxx 装了最新版但不兼容——整个项目跑崩
13.1 requirements.txt vs pyproject.toml 对比¶
| 对比项 | requirements.txt | pyproject.toml |
|---|---|---|
| 格式 | 纯文本,一行一个包 | TOML 结构化 |
| 标准化 | 非标准 | PEP 621 标准 |
| 工具配置 | 不支持 | 可以集中放 pytest/ruff 等配置 |
| 适合 | 简单项目、部署 | 正式项目(2025 推荐) |
13.2 pyproject.toml 完整示例 [推荐]¶
# pyproject.toml —— 项目的中央配置文件(一个文件管所有)
[build-system]
requires = ["hatchling"] # 构建后端
build-backend = "hatchling.build" # 指定构建工具
[project]
name = "t2d-api" # 项目名
version = "1.0.0" # 版本号
description = "2型糖尿病肠道菌群分析平台" # 描述
requires-python = ">=3.12" # Python 版本要求
license = {text = "MIT"} # 许可证
authors = [
{name = "你的名字", email = "your@email.com"},
]
# === 生产依赖 ===
dependencies = [
"fastapi>=0.115", # Web 框架
"uvicorn[standard]>=0.32", # ASGI 服务器
"gunicorn>=23.0", # 进程管理器
"pydantic-settings>=2.6", # 配置管理
"sqlalchemy>=2.0", # ORM
"aiosqlite>=0.20", # SQLite 异步驱动
"loguru>=0.7", # 日志
"python-multipart>=0.0.12", # 文件上传支持
]
# === 开发/测试依赖(两种写法任选其一) ===
# 写法 1(传统,兼容性好):[project.optional-dependencies]
# 安装方式:pip install -e ".[dev]"
[project.optional-dependencies]
dev = [
"pytest>=8.0", # 测试框架
"pytest-cov>=6.0", # 测试覆盖率
"pytest-asyncio>=0.24", # 异步测试支持
"httpx>=0.27", # 异步 HTTP 客户端(测试用)
"ruff>=0.8", # 代码检查+格式化
"pre-commit>=4.0", # Git 钩子
"commitizen>=4.0", # 提交规范
"pip-audit>=2.7", # 依赖漏洞扫描
]
# 写法 2(2025+ 新标准,PEP 735):[dependency-groups]
# uv 和 pip 24.3+ 原生支持,安装方式:uv add --dev pytest
# [dependency-groups]
# dev = [
# "pytest>=8.0",
# "pytest-cov>=6.0",
# "pytest-asyncio>=0.24",
# "httpx>=0.27",
# "ruff>=0.8",
# "pre-commit>=4.0",
# "commitizen>=4.0",
# "pip-audit>=2.7",
# ]
# 区别:[dependency-groups] 是专门给开发工具用的,不会被打包发布
# 如果用 uv,它会自动写入 [dependency-groups] 而非 [project.optional-dependencies]
# === Ruff 配置(一个工具替代 Black + Flake8 + isort) ===
[tool.ruff]
target-version = "py312" # 目标 Python 版本
line-length = 120 # 行宽限制
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort(import 排序)
"B", # flake8-bugbear
"S", # flake8-bandit(安全检查)
"UP", # pyupgrade(语法升级建议)
]
# === pytest 配置 ===
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "-v --cov=app --cov-report=term-missing"
asyncio_mode = "auto"
# === 覆盖率配置 ===
[tool.coverage.report]
fail_under = 80
show_missing = true
# === commitizen 配置 ===
[tool.commitizen]
name = "cz_conventional_commits" # 使用 conventional commits 规范
version = "1.0.0" # 和 [project] 中的 version 保持一致
tag_format = "v$version" # 标签格式:v1.0.0
13.3 依赖锁定 [推荐]¶
# === 方案 1(推荐):uv lock ===
# uv 项目模式自动维护 uv.lock 锁文件
uv lock # 手动生成/更新 uv.lock
uv sync # 从 uv.lock 精确安装(保证一致性)
uv run pytest # uv run 每次执行前自动检查并同步
# uv.lock 是跨平台的,包含每个平台的精确依赖树
# 【重要】uv.lock 必须提交到 Git,它才是真正的"锁定"
# 如果生产环境不用 uv,可以导出传统 requirements.txt:
uv export --format requirements-txt > requirements.txt # 从 uv.lock 导出
# === 方案 2:pip-compile(pip-tools 提供,传统方案) ===
pip install pip-tools # 安装 pip-tools
pip-compile pyproject.toml -o requirements.txt # 从 pyproject.toml 生成锁定文件
# 锁定文件包含精确版本号,确保不同环境安装完全一致的依赖
# 从锁定文件安装(确保版本一致)
pip install -r requirements.txt # 精确安装锁定版本
为什么要锁定?
pyproject.toml写的是fastapi>=0.115(范围),锁文件写的是fastapi==0.115.6(精确版本)。没有锁文件,两个人pip install可能装出不同版本,导致"我电脑上能跑"的经典问题。
13.4 安全漏洞扫描 [推荐]¶
# pip-audit:扫描已安装的包是否有已知漏洞
pip install pip-audit # 安装
pip-audit # 扫描当前环境
# 输出示例:
# Found 1 known vulnerability in 1 package
# Name Version ID Fix Versions
# ------- -------- --------------- ------------
# pillow 9.5.0 PYSEC-2023-175 10.0.1
# 自动修复(升级有漏洞的包)
pip-audit --fix # 自动升级到修复版本
# 在 CI 中使用
pip-audit -r requirements.txt # 扫描 requirements.txt 中的依赖
在 GitHub Actions 中集成漏洞扫描:
13.5 工具对比总结¶
| 工具 | 用途 | 是否免费 | 推荐度 |
|---|---|---|---|
| pip-audit | 依赖漏洞扫描 | 免费开源 | 首选 |
| Safety | 依赖漏洞扫描 | 免费版有限制 | 备选(付费版数据更全) |
| Ruff | 代码检查+格式化 | 免费开源 | 必装(替代 Black+Flake8+isort) |
| uv | 包管理器 | 免费开源 | 推荐(替代 pip,快 10-100 倍) |
| pip-tools | 依赖锁定 | 免费开源 | 稳妥之选 |
快速参考:13 项工程化规范优先级¶
| # | 规范 | 必须 | 推荐 | 进阶 |
|---|---|---|---|---|
| 1 | Git 初始化 + .gitignore | x | ||
| 1 | Conventional Commits | x | ||
| 1 | Tag 版本标记 | x | ||
| 2 | 分支策略(GitHub Flow) | x | ||
| 2 | 保护主分支 | x | ||
| 3 | SSH Key + 远程仓库 | x | ||
| 3 | 双平台推送 | x | ||
| 4 | .env 环境分离 | x | ||
| 4 | 虚拟环境 | x | ||
| 5 | CI/CD(GitHub Actions) | x | ||
| 5 | 部署脚本 | x | ||
| 6 | 单元测试 + pytest | x | ||
| 6 | 测试覆盖率 80% | x | ||
| 7 | 日志系统(loguru) | x | ||
| 7 | 日志轮转 | x | ||
| 8 | 数据库备份脚本 | x | ||
| 8 | cron 定时备份 | x | ||
| 8 | 远程备份 | x | ||
| 9 | systemd 服务 | x | ||
| 9 | 健康检查端点 | x | ||
| 9 | 外部监控 | x | ||
| 10 | Nginx 反向代理 | x | ||
| 10 | HTTPS (Certbot) | x | ||
| 10 | Cloudflare | x | ||
| 11 | UFW 防火墙 | x | ||
| 11 | SSH 加固 | x | ||
| 11 | Fail2Ban | x | ||
| 11 | 安全响应头 | x | ||
| 12 | README | x | ||
| 12 | API 文档(自动生成) | x | ||
| 12 | CHANGELOG | x | ||
| 13 | pyproject.toml | x | ||
| 13 | 依赖锁定 | x | ||
| 13 | 漏洞扫描 | x |
推荐的实施顺序¶
如果你是从零开始,按这个顺序来:
第 1 天:Git 初始化 + .gitignore + 远程仓库 + SSH Key
第 2 天:虚拟环境 + pyproject.toml + .env 环境分离
第 3 天:写好 README + FastAPI 自带文档配置好
第 4 天:日志系统配置(loguru)
第 5 天:pytest 测试 + 覆盖率
第 6 天:pre-commit + Ruff + commitizen
第 7 天:服务器部署:systemd + Nginx + HTTPS
第 8 天:安全加固:UFW + SSH + Fail2Ban
第 9 天:数据库备份 + cron 定时任务
第 10 天:CI/CD (GitHub Actions)
第 11 天:健康检查 + 外部监控
第 12 天:CHANGELOG + 漏洞扫描 + 查漏补缺
参考资源¶
FastAPI 项目结构与最佳实践: - FastAPI Best Practices (zhanymkanov) -- FastAPI 最佳实践汇总 - Production-Ready FastAPI Project Structure (2026 Guide) -- 生产级项目结构 - FastAPI Best Practices for Production (2026) -- 生产部署最佳实践 - FastAPI Setup Guide for 2025 -- FastAPI 环境搭建
Python 工具链与项目管理: - Python Project Setup 2026: uv + Ruff + Ty + Polars (KDnuggets) -- 2026 年 Python 工具链 - Managing Python Projects With uv (Real Python) -- uv 完整教程 - Python Packaging: pyproject.toml Guide -- 官方 pyproject.toml 指南 - Working on projects with uv -- uv 项目管理文档
部署与运维: - Deploy FastAPI on Ubuntu 24.04 (Gunicorn + Nginx + Certbot) -- Ubuntu 部署全流程 - Deploy FastAPI Like a Pro: GitHub Actions, GitLab CI -- CI/CD + 零停机部署 - Enhancing GitHub Actions CI for FastAPI (PyImageSearch) -- CI 进阶 - FastAPI Deployment Guide (RamNode) -- 服务器部署指南
日志系统: - Choosing a Python Logging Library in 2026 (Dash0) -- Python 日志库选型 - Python Logging with Loguru (Dash0) -- Loguru 生产配置 - Python Logging with Structlog (Dash0) -- Structlog 结构化日志 - Logging in Python: Top 6 Libraries (Better Stack) -- 日志库对比
Git 与分支策略: - Choosing the Right Git Strategy in 2025 -- Git 分支策略对比 - Agile Git Branching Strategies in 2026 (Java Code Geeks) -- 2026 分支策略趋势 - Effortless Code Quality: Pre-Commit Hooks Guide 2025 -- pre-commit 最佳实践
测试: - Testing FastAPI Applications with Pytest -- FastAPI 测试实战 - FastAPI Testing Strategies (greeden.me) -- 测试策略全景
安全: - Linux Server Hardening: SSH + Fail2Ban + UFW -- 服务器安全加固 - Harden Your Linux Server: Fail2Ban and UFW (VPS.DO) -- Fail2Ban 配置 - VPS Security Hardening Checklist 2025 (VPS.DO) -- 安全加固清单 - Hardening SSH 2025 Best Settings -- SSH 加固详解 - pip-audit (PyPI) -- 依赖漏洞扫描