FastAPI 部署到 VPS:Gunicorn + Nginx 生产环境搭建

概述

你的 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 管流量。搞定了这三层,你的服务就稳稳的了。

你的项目现在部署到哪儿了?有没有遇到过进程挂了没人知道的情况?

这篇文章对你有帮助吗?