FastAPI 部署实战:从 0 到上线,一篇彻底搞定!
FastAPI 作为 Python 高性能异步 Web 框架,部署上线却是很多开发者的痛点。本文从环境准备开始,手把手带你完成 FastAPI 生产环境部署,包含 Uvicorn/Gunicorn 启动、Docker 容器化、开机自启、日志配置等全套流程。从零到一,一篇吃透,看完直接照着部署,告别各种坑!
一、核心知识点
1. ASGI/WSGI 核心概念澄清
- FastAPI 是 ASGI 框架(异步),不能直接运行,仅支持 ASGI 服务器(uvicorn/daphne/hypercorn),
gunicorn本身是 WSGI 服务器,需通过uvicorn.workers.UvicornWorker适配 ASGI 应用。 - 生产环境:
gunicorn(进程管理) +uvicorn(异步工作进程)是行业标准,而非直接用 gunicorn 运行。
2. 版本兼容性
| 组件 | 推荐稳定版本 | 兼容说明 |
|---|---|---|
| Python | 3.8~3.11 | 3.12+ 在 CentOS7 需手动编译 OpenSSL 1.1.1 |
| FastAPI | 0.103.1 ~ 0.115.0 | 0.135+ 对 Python 3.9 兼容性略降 |
| Uvicorn | 0.24.0 ~ 0.27.1 | 与 FastAPI 大版本匹配 |
| Gunicorn | 21.2.0 ~ 25.3.0 | 25.x 需 Python 3.7+ |
| pydantic-settings | 2.1.0 ~ 2.13.1 | 2.x 仅支持 Python 3.8+ |
二、第一步:编写基础代码
1. 项目结构
fastapi-project/
├── app/ # 主应用目录
│ ├── __init__.py
│ ├── main.py # FastAPI 入口
│ └── settings.py # 多环境配置
├── .env.dev # 开发环境变量
├── .env.test # 测试环境变量
├── .env.prod # 生产环境变量
├── requirements.txt # 依赖
├── gunicorn_conf.py # 生产环境标准配置
├── Dockerfile # Docker 构建文件
└── docker-compose.yml # Docker 一键启动
2. requirements.txt
fastapi>=0.135.2
uvicorn[standard]>=0.42.0
gunicorn>=25.3.0 # 生产环境用
python-dotenv>=1.2.2 # 多环境配置
pydantic-settings>=2.13.1 # 官方推荐环境配置
3. gunicorn_conf.py
# Gunicorn 配置文件
# 用于生产环境启动 FastAPI 应用的 WSGI 服务器配置
# 官方文档:https://docs.gunicorn.org/en/stable/settings.html
# ========================== 基础配置 ==========================
# 监听的地址和端口
# 0.0.0.0 表示允许外部访问,8000 是服务端口
bind = "0.0.0.0:8002"
# 后台运行(守护进程)
# True:后台运行;False:前台运行(开发/调试用)
# daemon = True
daemon = False # Docker/Systemd 管理时关闭后台运行
# 进程 ID 存储文件路径(可选,用于管理进程)
# pidfile = "/tmp/gunicorn.pid"
pidfile = None # 容器化不需要 pid 文件
# ========================== 性能配置 ==========================
# 工作进程数(workers)
# 官方推荐公式:workers = 核心数 × 2 + 1
# 例如 4 核 CPU:workers = 9
# 容器环境建议:1~4 即可,避免资源占用过高
# workers = 2
workers = min(cpu_cores * 2 + 1, 8) # 上限 8,避免过多进程
# 工作模式(worker_class)
# FastAPI / ASGI 应用必须使用 uvicorn.workers.UvicornWorker
# 不能用默认的 sync 模式
worker_class = "uvicorn.workers.UvicornWorker"
# 每个工作进程的最大并发连接数
worker_connections = 1000
# 单个工作进程处理多少请求后自动重启(防止内存泄漏)
max_requests = 2000
# 随机偏移量,避免所有 worker 同时重启
max_requests_jitter = 100
# ========================== 超时配置 ==========================
# 客户端连接超时时间(秒)
# 生产环境建议 30~60
timeout = 30
# 优雅关闭超时时间(秒)
graceful_timeout = 10
# 保持连接超时(秒),HTTP/1.1 keep-alive
keepalive = 2
# ========================== 安全配置 ==========================
# 限制最大请求体大小(单位:字节)
# 50MB = 50 * 1024 * 1024
limit_request_line = 8190
limit_request_fields = 100
limit_request_field_size = 8190
# ========================== 调试配置 ==========================
# 调试模式(生产环境必须关闭)
debug = False
# 日志文件路径(可选,不配置则输出到控制台)
# accesslog = "/var/log/gunicorn/access.log"
# errorlog = "/var/log/gunicorn/error.log"
# 详细日志级别
# 可选:debug、info、warning、error、critical
loglevel = "info"
# ========================== 容器环境优化 ==========================
# Docker / Kubernetes 环境下必须开启
# 让 Gunicorn 正确接收容器的停止信号(SIGTERM/SIGINT)
forwarded_allow_ips = "*"
proxy_allow_ips = "*"
# 不使用缓冲输出,日志实时输出到控制台(Docker 日志收集必备)
capture_output = True
4. app/main.py(核心接口)
from fastapi import FastAPI
from app.settings import settings
# 创建 FastAPI 实例
app = FastAPI(
title="FastAPI 部署实例",
version="1.0.0",
debug=settings.DEBUG # 从环境配置读取
)
# 测试接口
@app.get("/")
def index():
return {
"msg": "FastAPI 部署成功",
"env": settings.ENV, # 当前环境
"debug": settings.DEBUG, # 是否调试模式
"port": settings.PORT # 端口
}
5. app/settings.py(多环境配置核心)
import os
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
# 环境变量名称(必须大写)
ENV: str = "dev" # 环境:dev/test/prod
DEBUG: bool = True # 调试模式
PORT: int = 8000 # 端口
HOST: str = "0.0.0.0" # 监听地址
# 配置优先级:命令行 > 系统环境变量 > 指定 env 文件 > 默认值
model_config = SettingsConfigDict(
env_file=f".env.{os.getenv('ENV', 'dev')}", # 动态加载环境文件
env_file_encoding="utf-8",
case_sensitive=True, # 严格区分环境变量大小写
extra="ignore" # 忽略未定义的环境变量
)
# 实例化配置
settings = Settings()
6. 多环境 .env 文件
.env.dev(开发)
ENV=dev
DEBUG=True
PORT=8000
.env.test(测试)
ENV=test
DEBUG=True
PORT=8001
.env.prod(生产)
ENV=prod
DEBUG=False
PORT=8002
三、Windows 系统部署
1. 安装 Python 3.13+
2. 安装依赖
cd fastapi-project
pip install -r requirements.txt
3. 开发环境启动
# 默认加载 .env
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
4. 指定环境启动(核心:多环境切换)
# 开发
uvicorn app.main:app --env-file .env.dev --reload
# 测试
uvicorn app.main:app --env-file .env.test --reload
# 生产
uvicorn app.main:app --env-file .env.prod
5. Windows 生产后台运行(无关闭窗口中断)
使用 start 后台运行:
start /b uvicorn app.main:app --host 0.0.0.0 --port 8002 --env-file .env.prod
访问:
http://127.0.0.1:8000
http://127.0.0.1:8001
http://127.0.0.1:8002
6. Windows 下杀死后台运行的 Uvicorn 进程
你用 start /b 启动的后台进程,可通过端口或进程 ID杀死,步骤如下:
方法 1:通过端口号杀死(推荐)
-
打开 cmd 执行命令,查找占用 8002 端口的进程 PID:
netstat -ano | findstr :8002输出示例:
TCP 0.0.0.0:8002 0.0.0.0:0 LISTENING 4144(4144就是进程 PID)。 -
根据 PID 杀死进程:
taskkill /F /PID 4144/F:强制终止进程- 替换
4144为你查到的实际 PID。
方法 2:通过进程名杀死(批量终止 Uvicorn)
如果启动了多个 Uvicorn 进程,可直接按进程名杀死:
taskkill /F /IM python.exe /T
/IM:指定进程名(Python 运行 Uvicorn,进程名是 python.exe)/T:终止进程及子进程
方法 3:任务管理器图形化操作
- 按下
Ctrl + Shift + Esc打开任务管理器。 - 切换到详细信息标签,找到python.exe进程(对应 PID 为 4144 的那个)。
- 右键选择结束任务,或选中后点击结束任务按钮。
方法 4:通过进程名查端口号杀死
第一步:获取进程的 PID 列表
执行命令列出所有python.exe的 PID:
tasklist | findstr /i python.exe
输出示例:
python.exe 4144 Console 1 100,200 K
python.exe 5678 Console 1 89,500 K
其中4144、5678是python.exe的 PID。
第二步:根据 PID 查占用端口
执行命令关联 PID 和端口:
netstat -ano | findstr /i "LISTENING" | findstr "4144"
输出示例:
TCP 0.0.0.0:8002 0.0.0.0:0 LISTENING 4144
即可看到python.exe(PID 4144)占用了8002 端口。
一键查询脚本(自动匹配进程名 + 端口)
新建check_port_by_process.bat批处理文件,输入以下代码,可直接根据进程名查端口:
@echo off
set /p process_name=请输入进程名(如python.exe):
echo.
echo 正在查询进程 [%process_name%] 的PID...
tasklist | findstr /i %process_name%
echo.
echo 正在查询PID对应的端口...
for /f "tokens=2" %%a in ('tasklist ^| findstr /i %process_name% ^| findstr /i "Console"') do (
netstat -ano | findstr /i "LISTENING" | findstr %%a
)
echo.
pause
7. nssm 部署
(1)更优雅的后台运行(替代 start /b)
使用 nssm(Non-Sucking Service Manager)将 FastAPI 注册为 Windows 服务:
# 1. 下载 nssm(https://nssm.cc/download)
# 2. 注册服务
nssm install FastAPI-Prod "C:\Python39\python.exe" "C:\Python39\Scripts\uvicorn.exe app.main:app --host 0.0.0.0 --port 8002 --env-file .env.prod"
# 3. 启动服务
nssm start FastAPI-Prod
# 4. 停止/删除服务
nssm stop FastAPI-Prod
nssm remove FastAPI-Prod confirm
(2)端口占用检测脚本(批处理)
新建 check_port.bat:
@echo off
set /p port=请输入要检测的端口:
netstat -ano | findstr :%port% > nul
if %errorlevel% equ 0 (
echo 端口 %port% 已被占用!PID 信息:
netstat -ano | findstr :%port%
) else (
echo 端口 %port% 未被占用
)
pause
四、CentOS7 部署(生产标准)
1. 安装 Python 3.9
- Python 3.9 是 CentOS7 官方兼容的新版本,编译时能正常调用系统的 OpenSSL 1.0.2k,生成
_ssl模块;- 避开了 Python 3.13 对 OpenSSL 1.1.1+ 的高版本要求,从根源解决模块缺失问题;
- Python 3.9 完全支持 FastAPI 0.135.2 所有功能,不影响项目开发和部署。
1.1. 安装 CentOS7 编译依赖(必须执行)
yum install -y gcc gcc-c++ make openssl-devel bzip2-devel libffi-devel zlib-devel wget curl xz
1.2. 下载并编译安装 Python 3.9.19
# 进入安装目录
cd /usr/local/src
# 下载 Python 3.9.19
wget https://www.python.org/ftp/python/3.9.19/Python-3.9.19.tgz
# 解压
tar -xvf Python-3.9.19.tgz
cd Python-3.9.19
# 清理之前失败的编译文件(如果之前未编译失败,可忽略)
make clean
make distclean
# 编译配置 CentOS7 的系统太老,开启 --enable-optimizations 编译会失败!
./configure
# 编译(-j 代表CPU核心数,加速编译)
make -j4
# 安装(不替换系统自带Python,安全)
make altinstall
1.3. 验证是否安装成功
python3.9 --version
pip3.9 --version
出现版本号即成功。
1.4. Python 到底安装在哪里?
👉 默认安装路径(CentOS7 + make altinstall)
python
/usr/local/bin/python3.9
pip
/usr/local/bin/pip3.9
👉 安装目录完整路径:
/usr/local/lib/python3.9/
👉 你可以用这条命令查看真实位置:
which python3.9
输出一定是
/usr/local/bin/python3.9
查看安装目录所有文件
ls -l /usr/local/bin | grep python
ls -l /usr/local/lib | grep python
系统自带 Python 在哪里?(2.7)
/usr/bin/python
所以:
python= 系统 2.7python3.9= 你新装的 3.9.19
1.5. 配置国内镜像源
# 一键配置阿里云镜像(最快、最稳)
pip3.9 config set global.index-url http://mirrors.aliyun.com/pypi/simple/
pip3.9 config set global.trusted-host mirrors.aliyun.com
1.6. 升级 pip(必须)
pip3.9 install --upgrade pip
2. 安装依赖
# 进入项目
cd /root/fastapi-project
# 安装依赖
python3.9 -m pip install -r requirements.txt
3. 直接运行(开发 / 测试)
# 开发
python3.9 -m uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload --env-file .env.dev
# 测试
python3.9 -m uvicorn app.main:app --host 0.0.0.0 --port 8001 --env-file .env.test
4. 生产级启动(gunicorn + uvicorn)【正式环境必须用】
Gunicorn 是 Linux/Mac 专用的 WSGI 服务器,完全不支持 Windows 系统!
新建 gunicorn_conf.py
# gunicorn 配置
bind = "0.0.0.0:8002" # 监听端口
workers = 4 # 进程数 = CPU核心 * 2 + 1
worker_class = "uvicorn.workers.UvicornWorker" # 使用 uvicorn
timeout = 120
keepalive = 5
运行:
gunicorn app.main:app -c gunicorn_conf.py --env ENV_FILE=.env.prod
5. 后台守护运行(关闭终端不关闭服务)
nohup gunicorn app.main:app -c gunicorn_conf.py > app.log 2>&1 &
查看日志:
tail -f app.log
关闭进程:
pkill gunicorn
6. 一键脚本
CentOS 7.9 + Python 3.9 一套到底的完整部署方案,跟 Java jar 一样省心。
6.1. 最终稳定版:requirements.txt
fastapi==0.115.0
uvicorn==0.27.1
gunicorn==21.2.0
pydantic-settings==2.1.0
python-dotenv==1.0.1
安装命令:
python3.9 -m pip install -r requirements.txt
6.2. 启动脚本:run.sh
#!/bin/bash
nohup python3.9 -m gunicorn app.main:app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8001 > app.log 2>&1 &
echo "FastAPI 已后台启动,端口:8001"
加权限并运行:
chmod +x run.sh
./run.sh
6.3. 停止脚本:stop.sh
#!/bin/bash
pkill -f gunicorn
echo "FastAPI 已停止"
加权限:
chmod +x stop.sh
./stop.sh
6.4. 查看日志
tail -f app.log
6.5. 查看是否在运行
ps -ef | grep gunicorn
7. Systemd 服务管理(替代 nohup)
创建 /usr/lib/systemd/system/fastapi.service:
[Unit]
Description=FastAPI Production Service
After=network.target
[Service]
User=root
Group=root
WorkingDirectory=/root/fastapi-project
Environment="ENV=prod"
ExecStart=/usr/local/bin/gunicorn app.main:app -c gunicorn_conf.py
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -TERM $MAINPID
Restart=on-failure
RestartSec=5s
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
启动 / 管理命令:
systemctl daemon-reload
systemctl start fastapi
systemctl enable fastapi # 开机自启
systemctl status fastapi
journalctl -u fastapi -f # 查看日志
防火墙配置:
# 开放 8002 端口
firewall-cmd --zone=public --add-port=8002/tcp --permanent
firewall-cmd --reload
# 查看开放端口
firewall-cmd --list-ports
五、Docker 部署(最推荐、跨平台一致)
Windows / Mac / CentOS / Ubuntu 完全一样
1. 创建 Python3.9 镜像
方式一: 创建本地镜像
步骤1:创建最简单的 Dockerfile(完全本地,不 FROM 任何外网)
FROM centos:7
# 替换为阿里云源
RUN rm -rf /etc/yum.repos.d/*.repo \
&& curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo \
&& yum clean all \
&& yum makecache
# 安装编译依赖(只装系统库,不联网下载Python)
RUN yum install -y gcc openssl-devel bzip2-devel libffi-devel zlib-devel make
# 把宿主机当前目录的 Python-3.9.19.tgz 复制到镜像里
COPY Python-3.9.19.tgz /usr/local/src/
# 编译安装 Python 3.9
RUN cd /usr/local/src \
&& tar xzf Python-3.9.19.tgz \
&& cd Python-3.9.19 \
&& ./configure \
&& make -j2 \
&& make altinstall
# 阿里云 pip 源
RUN pip3.9 config set global.index-url http://mirrors.aliyun.com/pypi/simple/ \
&& pip3.9 config set global.trusted-host mirrors.aliyun.com \
&& pip3.9 config set global.root-user-action ignore
# 安装依赖
#RUN pip install --no-cache-dir \
# fastapi==0.115.0 \
# uvicorn==0.27.1 \
# gunicorn==21.2.0 \
# pydantic-settings==2.1.0 \
# python-dotenv==1.0.1
# 这里不配置任何网络源!避免失败
WORKDIR /app
# 默认启动命令
CMD ["python3.9"]
步骤2:构建 python 镜像(本地自己编译,不联网拉取任何镜像)
docker build -t python:3.9 .
方式二: 获取远程镜像
# 远程拉取镜像
docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/python:3.9-slim
# 给原镜像打一个新的标签
docker tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/python:3.9-slim python:3.9
# 一行命令合并执行,拉取时直接改名
docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/python:3.9-slim && docker tag $_ python:3.9
2. 编写 Dockerfile
# 直接使用本地基础镜像
FROM python:3.9
# 设置工作目录
WORKDIR /app
# 关键:指定环境为 prod
ENV ENV_FILE=.env.prod
# 复制项目代码
COPY . .
# 安装依赖
RUN pip3.9 install --no-cache-dir -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/
# 暴露多个端口
EXPOSE 8000
EXPOSE 8001
EXPOSE 8002
# 生产启动命令
CMD ["gunicorn", "app.main:app", "-c", "gunicorn_conf.py"]
-i https://mirrors.aliyun.com/pypi/simple/加这一行!指定国内镜像源,秒解决网络不通
3. 编写 docker-compose.yml(一键多环境)
version: '3'
services:
# 开发环境
fastapi-dev:
build: .
container_name: fastapi-dev
ports:
- "8000:8000"
env_file:
- .env.dev
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
# 测试环境
fastapi-test:
build: .
container_name: fastapi-test
ports:
- "8001:8001"
env_file:
- .env.test
command: uvicorn app.main:app --host 0.0.0.0 --port 8001
# 生产环境
fastapi-prod:
build: .
container_name: fastapi-prod
ports:
- "8002:8002"
env_file:
- .env.prod
command: gunicorn app.main:app -c gunicorn_conf.py
4. 构建项目镜像
docker build -t fastapi-app:v1 .
5. 创建启动容器
docker run -d \
--restart=always \
-p 8002:8002 \
--env-file .env.prod \
--name my-fastapi \
fastapi-app:v1
要点:
--env-file .env.prod:加载生产环境变量(ENV=prod、DEBUG=False 等)- 最后面覆盖启动命令:用 gunicorn
- 只映射 8002,不要同时映射 8000/8001
6. 验证是否正确
# 访问项目
http://192.168.133.68:8002/
# 接口文档:
http://192.168.133.68:8002/docs
访问 http://192.168.133.68:8002/ 应该返回:
{
"msg": "FastAPI 部署成功",
"env": "prod",
"debug": false,
"port": 8002
}
7. 常用命令
# 验证是否真的加载了 prod
docker exec my-fastapi env | grep ENV_FILE
# 查看运行状态
docker ps
# 查看日志
docker logs -f my-fastapi
# 停止服务
docker stop my-fastapi
# 重启服务
docker restart my-fastapi
# 查看运行状态
docker ps
六、运维与安全实践
1.故障排查指南
| 问题现象 | 排查方向 | 解决方案 |
|---|---|---|
启动报错 ImportError: No module named '_ssl' |
Python 编译未关联 OpenSSL | 重新编译 Python,指定 --with-openssl 路径 |
| Gunicorn 启动后无法访问 | 端口未开放 / 绑定地址错误 | 检查防火墙 + 确认 bind = 0.0.0.0: 端口 |
| Docker 日志无输出 | PYTHONUNBUFFERED 未设置 | 添加环境变量 PYTHONUNBUFFERED=1 |
| 内存泄漏 | Worker 未配置 max_requests | 启用 max_requests + max_requests_jitter |
| 多环境配置不生效 | env_file 路径错误 / 优先级问题 | 用 docker exec 容器 env 检查环境变量 |
2.多环境切换总结
| 环境 | 启动命令 | 管理方式 | 监控方式 |
|---|---|---|---|
| 开发 | uvicorn app.main:app --reload --env-file .env.dev |
手动启动 | 控制台日志 + /docs 调试 |
| 测试 | uvicorn app.main:app --env-file .env.test |
Systemd/nohup | 日志文件 + 健康检查接口 |
| 生产 | gunicorn app.main:app -c gunicorn_conf.py |
Docker + Systemd | Nginx 日志 + 容器监控 + 告警 |
3.安全最佳实践
- 生产环境关闭
DEBUG、docs_url、redoc_url; - 使用非 root 用户运行服务(Docker / 系统);
- 配置请求体大小限制,防止超大请求攻击;
- 启用 HTTPS(Nginx 配置 SSL 证书);
- 定期更新依赖包,修复安全漏洞(
pip audit检查); - 限制容器 / 进程的 CPU / 内存资源,防止资源耗尽。
更多推荐
所有评论(0)