Systemd + Uvicorn + FastAPI 部署

目录

使用 Uvicorn 运行 FastAPI,由 systemd 管理服务的启动、停止和异常重启,NGINX 负责对外提供反向代理。

下面以使用 systemd 的 Ubuntu / Debian 服务器为例,应用目录为 /home/fastapi-user/fastapi-app,入口为 server.py 中的 app 实例。部署已有项目时,需要按实际情况修改路径和入口。

设置 FastAPI 应用程序

一般本机开发,远程使用 git 拉取代码,并配置环境

原生 python
1
2
3
4
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
UV 管理
1
uv sync

配置 systemd

创建服务文件
1
sudo vim /etc/systemd/system/fastapi-app.service

添加以下内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
[Unit]
Description=FastAPI application served by Uvicorn
After=network.target

[Service]
Type=simple
User=fastapi-user
Group=fastapi-user
WorkingDirectory=/home/fastapi-user/fastapi-app
Environment="PYTHONUNBUFFERED=1"
ExecStart=/home/fastapi-user/fastapi-app/.venv/bin/python -m uvicorn server:app --host 127.0.0.1 --port 8000 --workers 1 --proxy-headers --forwarded-allow-ips=127.0.0.1 --timeout-graceful-shutdown 30
Restart=on-failure
RestartSec=5
KillMode=mixed
TimeoutStopSec=60
StandardOutput=journal
StandardError=journal
SyslogIdentifier=fastapi-app

[Install]
WantedBy=multi-user.target

主要配置说明:

  • User、Group:运行应用的用户和用户组。
  • WorkingDirectory:应用工作目录,server.py 位于此目录下。
  • ExecStart:直接使用虚拟环境中的 Python 启动 Uvicorn,无需执行 source activate。
  • Restart=on-failure:进程异常退出时自动重启;通过 systemctl stop 主动停止服务不会触发重启。
  • KillMode=mixed:停止时先向主进程发送终止信号,让它协调 worker 退出;超时后清理剩余进程。
  • TimeoutStopSec:systemd 等待服务停止的时间,给 Uvicorn 的优雅退出留出余量。
  • StandardOutput、StandardError:将标准输出和错误输出交给 journal 收集。

systemd 的重启与停止行为可参考 systemd.service 和 systemd.kill。

Uvicorn 参数说明:

  • server:app:表示导入 server.py 中的 app;如果入口是 app/main.py,通常改为 app.main:app。
  • --workers 1:启动一个工作进程,可根据内存和负载调整。使用多 worker 时,各进程的内存相互独立,应用启动逻辑也会在各 worker 中分别执行。
  • --reload:生产环境不要加此参数,它与 --workers 不能同时使用。
  • --proxy-headers 配合 --forwarded-allow-ips=127.0.0.1:只信任本机代理转发的客户端地址和协议头。

参数含义见 Uvicorn Settings。

启动服务并设置开机启动
1
2
3
4
sudo systemctl daemon-reload
sudo systemctl enable --now fastapi-app
sudo systemctl status fastapi-app --no-pager
curl http://127.0.0.1:8000/health

active (running) 表示服务进程正在运行,还需要通过 HTTP 请求确认应用已经正常提供服务。

查看日志
1
2
3
4
5
# 查看最近 100 行日志
sudo journalctl -u fastapi-app -n 100 --no-pager

# 实时查看日志
sudo journalctl -u fastapi-app -f

NGINX 中的配置

创建站点配置:

1
sudo nano /etc/nginx/sites-available/fastapi-app.conf

添加以下内容,将 api.example.com 替换为实际域名,并将域名解析到服务器:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
server {
    listen 80;
    server_name api.example.com;

    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 $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_redirect off;
    }
}

这里按 NGINX 直接面向客户端的单层代理配置,覆盖客户端传入的 X-Forwarded-For。如果前面还有 CDN 或负载均衡,需要额外配置可信代理与真实客户端 IP。

启用站点并检查配置,下面的软链接命令只需首次执行:

1
2
sudo ln -s /etc/nginx/sites-available/fastapi-app /etc/nginx/sites-enabled/fastapi-app
sudo nginx -t

检查通过后启动 NGINX 并重新加载配置:

1
2
3
sudo systemctl enable --now nginx
sudo systemctl reload nginx
curl -H 'Host: api.example.com' http://127.0.0.1/health

此时可以通过 http://api.example.com/docs 访问 FastAPI 的接口文档。服务器安全组或防火墙需要允许 HTTP 的 80 端口;Uvicorn 仅监听本机地址,无需开放 8000 端口。对外正式使用时应进一步配置 HTTPS。

更新与维护

更新应用

更新项目代码和依赖时,使用 fastapi-user 执行

1
2
3
4
5
6
sudo -iu fastapi-user
cd /home/fastapi-user/fastapi-app
git pull
exit
sudo systemctl restart fastapi-app
curl http://127.0.0.1:8000/health

按实际项目选择依赖安装命令。如果只使用本文的最小示例,修改 server.py 后重启服务即可。restart 会有短暂服务中断,请求检查若遇到应用尚未启动完成,可以查看日志后重试。

修改 .service 文件后,需要重新加载 systemd 配置并重启:

1
2
sudo systemctl daemon-reload
sudo systemctl restart fastapi-app
常用管理命令
1
2
3
4
5
6
7
sudo systemctl start fastapi-app
sudo systemctl stop fastapi-app
sudo systemctl restart fastapi-app
sudo systemctl status fastapi-app --no-pager

sudo nginx -t
sudo nginx -s reload

如果服务启动失败,先通过 journalctl 查看错误,重点检查虚拟环境路径、应用入口、文件权限以及端口占用。NGINX 返回 502 时,先在服务器执行 curl http://127.0.0.1:8000/health,确认后端是否正常,再检查 NGINX 配置和 /var/log/nginx/error.log。

发现新版本

当前站点有新版本可用。