概述
你的 FastAPI 项目在本地跑得好好的,一部署到 VPS 就各种问题:进程一挂就全完,并发扛不住,没有 HTTPS,日志乱成一锅粥。
问题出在你用了 uvicorn main:app --reload 这种开发模式。开发可以,生产不行。
这篇教程用 Gunicorn 做进程管理(自动重启、多 worker),Nginx 做反向代理(处理并发、HTTPS),把你的 FastAPI 项目变成生产级别的可靠服务。全程基于 Ubuntu 22.04/24.04,15分钟搞定。
准备工作
你需要以下条件:
- 一台 Ubuntu 22.04 或 24.04 VPS(2核4G起步,1核1G也能跑小项目)
- 已配置 SSH 登录和 sudo 权限
- 一个指向 VPS 的域名(用于 HTTPS,没有的话先用 IP 地址测试)
- 你的 FastAPI 项目代码(假设项目根目录在
~/myapp) - 约 200MB 磁盘空间
步骤
第一步:系统更新和基础依赖安装
sudo apt update && sudo apt upgrade -y
sudo apt install -y python3-pip python3-venv nginx certbot python3-certbot-nginx
python3-venv 是 Python 虚拟环境工具,certbot 用于自动申请 SSL 证书。
第二步:用虚拟环境安装项目依赖
cd ~/myapp
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
pip install gunicorn
你的 requirements.txt 里应该有 fastapi 和 uvicorn。gunicorn 单独安装,不用写进 requirements。
验证安装:
python -c "import fastapi; print(fastapi.__version__)"
第三步:测试 Gunicorn 能否正常运行
gunicorn -w 2 -k uvicorn.workers.UvicornWorker main:app --bind 0.0.0.0:8000
参数说明:
-w 2启动 2 个 worker 进程,根据 CPU 核数调整(推荐 2×核数+1)-k uvicorn.workers.UvicornWorker用 Uvicorn 的 async worker,支持高并发main:app表示导入main.py里的app对象
打开新终端测试:
curl http://localhost:8000/docs
看到 Swagger UI 页面就说明通了。按 Ctrl+C 退出测试,继续下一步。
第四步:配置 systemd 服务(关键步骤)
开发时用命令行启动没问题,但系统重启后进程不会自动拉起。用 systemd 管理服务,这才是生产做法。
创建服务文件:
sudo tee /etc/systemd/system/myapp.service > /dev/null << 'EOF'
[Unit]
Description=My FastAPI Application
After=network.target
[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/myapp
Environment="PATH=/home/ubuntu/myapp/venv/bin"
ExecStart=/home/ubuntu/myapp/venv/bin/gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app --bind 127.0.0.1:8000
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
注意:
User=ubuntu换成你 VPS 的实际用户名WorkingDirectory换成你的项目路径--bind 127.0.0.1:8000绑定本地,不对外暴露,安全Restart=on-failure进程崩了自动重启,RestartSec=5等 5 秒再试
加载并启动服务:
sudo systemctl daemon-reload
sudo systemctl enable myapp
sudo systemctl start myapp
sudo systemctl status myapp
状态应该是绿色的 active (running)。查看日志:
sudo journalctl -u myapp -f
第五步:配置 Nginx 反向代理
Gunicorn 跑在 127.0.0.1:8000,外面访问不到。Nginx 负责接收请求,转给 Gunicorn。
sudo tee /etc/nginx/sites-available/myapp > /dev/null << 'EOF'
server {
listen 80;
server_name your-domain.com; # 换成你的域名或IP
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $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;
proxy_redirect off;
proxy_buffering off;
}
location /static/ {
alias /home/ubuntu/myapp/static/;
expires 30d;
}
}
EOF
启用站点并测试配置:
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
第六步:配置 HTTPS(域名用户)
没有域名的可以跳过这步,先用 HTTP 跑起来。
sudo certbot --nginx -d your-domain.com
Certbot 会自动修改 Nginx 配置、申请证书、开启 HTTPS 重定向。跑完后访问 https://your-domain.com 应该能看到你的 API 文档。
第七步:配置静态文件和日志
如果你的 FastAPI 项目有静态资源(图片、CSS等):
mkdir -p ~/myapp/static
# 在 main.py 里挂载静态文件
from fastapi.staticfiles import StaticFiles
app.mount("/static", StaticFiles(directory="static"), name="static")
日志默认走 journalctl,也可以配置 Gunicorn 写到文件:
sudo tee /etc/systemd/system/myapp.service > /dev/null << 'EOF'
[Unit]
Description=My FastAPI Application
After=network.target
[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/myapp
Environment="PATH=/home/ubuntu/myapp/venv/bin"
ExecStart=/home/ubuntu/myapp/venv/bin/gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app --bind 127.0.0.1:8000 --access-logfile /var/log/myapp/access.log --error-logfile /var/log/myapp/error.log
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
创建日志目录:
sudo mkdir -p /var/log/myapp
sudo chown ubuntu:www-data /var/log/myapp
验证
部署完成后,按以下方式确认一切正常:
# 1. 检查服务状态
sudo systemctl status myapp
# 2. 检查 Gunicorn worker 数量
ps aux | grep gunicorn
# 3. 访问 API(HTTP)
curl http://localhost:8000/docs
# 4. 访问 API(HTTPS,有域名的话)
curl -I https://your-domain.com
# 5. 检查 Nginx 配置
sudo nginx -t
# 6. 查看实时日志
sudo journalctl -u myapp -f
一个健康的服务应该满足:systemd 状态是 active (running),至少 4 个 gunicorn worker 进程,curl 访问返回 200,HTTPS 证书有效。
常见问题
问:为什么 Gunicorn 绑定 127.0.0.1 而不是 0.0.0.0?
生产环境 Gunicorn 只监听本地,Nginx 负责对外。这样即使 Nginx 挂了,Gunicorn 也不会被直接暴露到公网,安全很多。
问:worker 数量怎么设置?
异步应用(FastAPI)推荐公式:2 × CPU核数 + 1。2核机器用 5 个 worker,4核用 9 个。太多 worker 会争抢内存,太少扛不住并发。
问:服务启动失败怎么办?
# 查看详细错误日志
sudo journalctl -u myapp -n 50 --no-pager
# 手动运行 Gunicorn 看报错
cd ~/myapp && source venv/bin/activate && gunicorn -w 2 -k uvicorn.workers.UvicornWorker main:app --bind 127.0.0.1:8000
问:代码更新了怎么热重载?
生产环境不要开 --reload。改完代码后重启服务即可:
sudo systemctl restart myapp
问:内存占用太高怎么办?
每个 worker 独立进程,内存是叠加的。如果 VPS 只有 1G 内存,把 worker 数降到 2,或者加 swap:
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
把 FastAPI 从开发模式搬到生产环境,核心就是三件事:systemd 管进程、Gunicorn 管并发、Nginx 管流量。搞定了这三层,你的服务就稳稳的了。
你的项目现在部署到哪儿了?有没有遇到过进程挂了没人知道的情况?