在 VPS 上使用 Gunicorn 和 Nginx 部署 Python Flask

Flask 是一款轻量级 Python Web 框架,非常适合构建 REST API、Web 应用和微服务。然而,Flask 内置的开发服务器并不适合生产环境——它只能处理有限的并发请求,且稳定性不足。正确的做法是通过 Gunicorn(WSGI 服务器)来运行 Flask,并在其前端使用 Nginx 作为反向代理。本教程将带您在 Ubuntu VPS 上完成一套完整的生产就绪部署方案。

最终成果:Flask App → Gunicorn → Nginx → 域名 + HTTPS,每次 VPS 重启后自动启动。

前置条件

第一步:更新服务器并安装 Python 3

Ubuntu 已预装 Python 3,但请先更新软件包:

sudo apt update && sudo apt upgrade -y sudo apt install python3 python3-pip python3-venv -y

验证安装是否成功:

python3 --version pip3 --version

第二步:创建 Flask 应用与虚拟环境

使用虚拟环境可以隔离每个项目的依赖,避免包版本冲突:

mkdir -p ~/myflaskapp && cd ~/myflaskapp python3 -m venv venv source venv/bin/activate

在虚拟环境中安装 Flask 和 Gunicorn:

pip install flask gunicorn

创建 app.py:

cat > app.py << 'EOF' from flask import Flask, jsonify app = Flask(__name__) @app.route('/') def index(): return jsonify({"message": "Hello from AsiaGB Flask App!", "status": "ok"}) @app.route('/health') def health(): return jsonify({"status": "healthy"}) if __name__ == '__main__': app.run(debug=False) EOF

创建 wsgi.py 作为 Gunicorn 的入口文件:

cat > wsgi.py << 'EOF' from app import app if __name__ == '__main__': app.run() EOF

测试 Gunicorn 是否正常运行:

gunicorn --bind 0.0.0.0:8000 wsgi:app

在浏览器中打开 http://YOUR_VPS_IP:8000,应该能看到 JSON 响应。按 Ctrl+C 停止。

第三步:为 Gunicorn 创建 systemd 服务

要在开机时自动启动 Flask 应用,需要创建 systemd 单元文件:

sudo nano /etc/systemd/system/myflaskapp.service

粘贴以下内容(将 YOUR_USERNAME 替换为实际用户名):

[Unit] Description=Gunicorn instance to serve Flask App After=network.target [Service] User=YOUR_USERNAME Group=www-data WorkingDirectory=/home/YOUR_USERNAME/myflaskapp Environment="PATH=/home/YOUR_USERNAME/myflaskapp/venv/bin" ExecStart=/home/YOUR_USERNAME/myflaskapp/venv/bin/gunicorn \ --workers 3 \ --bind unix:myflaskapp.sock \ -m 007 \ wsgi:app [Install] WantedBy=multi-user.target

需要几个 Worker?推荐公式为 2 × CPU 核心数 + 1。单核 VPS 使用 3 个 Worker,双核 VPS 使用 5 个 Worker。

启动并设置服务开机自启:

sudo systemctl start myflaskapp sudo systemctl enable myflaskapp sudo systemctl status myflaskapp

应看到 Active: active (running)。

第四步:安装并配置 Nginx

安装 Nginx:

sudo apt install nginx -y

为 Flask 应用创建 Nginx 配置文件:

sudo nano /etc/nginx/sites-available/myflaskapp

填入以下内容(替换域名和路径):

server { listen 80; server_name your-domain.com www.your-domain.com; location / { include proxy_params; proxy_pass http://unix:/home/YOUR_USERNAME/myflaskapp/myflaskapp.sock; } location /static { alias /home/YOUR_USERNAME/myflaskapp/static; expires 30d; add_header Cache-Control "public, no-transform"; } }

启用配置并测试:

sudo ln -s /etc/nginx/sites-available/myflaskapp /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl restart nginx

第五步:配置防火墙

sudo ufw allow 'Nginx Full' sudo ufw allow OpenSSH sudo ufw enable sudo ufw status

⚠️ 重要提示:启用 ufw 之前务必先放行 OpenSSH。否则您将立即被锁定在 VPS 之外。

第六步:使用 Certbot 安装免费 SSL 证书

安装 Certbot(Nginx 版):

sudo apt install certbot python3-certbot-nginx -y

申请 SSL 证书(域名必须已解析到该 VPS):

sudo certbot --nginx -d your-domain.com -d www.your-domain.com

Certbot 会自动更新 Nginx 配置,添加 HTTPS 跳转和 SSL 设置。测试自动续期:

sudo certbot renew --dry-run

测试重启后是否自动启动

sudo reboot

通过 SSH 重新连接后:

sudo systemctl status myflaskapp sudo systemctl status nginx

两者均应显示 active (running)。

常用管理命令

# 代码更改后重启 sudo systemctl restart myflaskapp # 实时查看 Gunicorn 日志 sudo journalctl -u myflaskapp -f # 实时查看 Nginx 访问/错误日志 sudo tail -f /var/log/nginx/access.log sudo tail -f /var/log/nginx/error.log # 编辑后测试 Nginx 配置 sudo nginx -t && sudo systemctl reload nginx

提升 Gunicorn 性能 — 异步 Worker 与连接调优

Gunicorn 默认的同步 Worker 每个 Worker 一次只处理一个请求。如果您的 Flask 应用 I/O 操作较多——例如调用外部 API、执行数据库查询或等待网络响应——切换到异步 Worker可让每个 Worker 同时处理数千个并发连接,而无需增加 CPU:

pip install gevent

更新 systemd 单元文件中的 ExecStart:

ExecStart=/home/YOUR_USERNAME/myflaskapp/venv/bin/gunicorn \ --workers 3 \ --worker-class gevent \ --worker-connections 1000 \ --timeout 60 \ --bind unix:myflaskapp.sock \ -m 007 \ wsgi:app
Worker 类型 适合场景 说明
sync(默认)CPU 密集型应用、简单 API每个 Worker 同时处理 1 个请求
geventI/O 密集型应用、外部 API 调用每个 Worker 可处理 1000+ 并发请求
gthread线程安全代码使用线程而非协程

编辑单元文件后,重新加载 systemd 并重启服务:

sudo systemctl daemon-reload sudo systemctl restart myflaskapp

为 Flask 配置 Nginx 缓存与速率限制

Nginx 可以缓存 Gunicorn 的响应以降低应用负载,并通过速率限制防止滥用。在 Nginx 配置中添加以下内容:

# 在 server 块外部 — 定义缓存区和速率限制区 proxy_cache_path /tmp/nginx_cache levels=1:2 keys_zone=flask_cache:10m max_size=100m inactive=60m; limit_req_zone $binary_remote_addr zone=api_limit:10m rate=30r/m; server { listen 443 ssl; server_name your-domain.com; # 缓存 API 响应 5 分钟 location /api/ { limit_req zone=api_limit burst=10 nodelay; proxy_cache flask_cache; proxy_cache_valid 200 5m; proxy_cache_use_stale error timeout; add_header X-Cache-Status $upstream_cache_status; include proxy_params; proxy_pass http://unix:/home/YOUR_USERNAME/myflaskapp/myflaskapp.sock; } # 动态端点跳过缓存 location / { proxy_no_cache 1; include proxy_params; proxy_pass http://unix:/home/YOUR_USERNAME/myflaskapp/myflaskapp.sock; } }

提示:在浏览器开发者工具的「网络」标签中检查响应头 X-Cache-Status: HIT / MISS,确认缓存是否生效。HIT 表示 Nginx 直接返回了缓存内容,未转发至 Gunicorn。

使用环境变量进行安全配置

将密钥、数据库地址或 API 令牌直接硬编码在代码中存在严重的安全隐患。正确做法是通过 systemd 单元文件在运行时以环境变量的方式注入密钥:

[Service] ... EnvironmentFile=/etc/myflaskapp/env ExecStart=...

创建环境变量文件并锁定权限:

sudo mkdir -p /etc/myflaskapp sudo nano /etc/myflaskapp/env

环境变量文件内容:

FLASK_SECRET_KEY=your-very-long-random-secret-key-here DATABASE_URL=mysql+pymysql://user:password@localhost/dbname REDIS_URL=redis://127.0.0.1:6379/0 FLASK_ENV=production

限制仅 root 可访问:

sudo chmod 600 /etc/myflaskapp/env sudo chown root:root /etc/myflaskapp/env

在 app.py 中通过 os.environ 读取密钥:

import os from flask import Flask app = Flask(__name__) app.secret_key = os.environ.get('FLASK_SECRET_KEY', 'fallback-dev-key') DATABASE_URL = os.environ.get('DATABASE_URL')

⚠️ 切勿将密钥提交到 Git。将 /etc/myflaskapp/env 及所有 .env 文件加入 .gitignore。公共仓库中泄露的凭证是生产环境安全事故最常见的原因之一。

故障排查

502 Bad Gateway

通常表示 Gunicorn 未运行。使用 sudo systemctl status myflaskapp 检查状态,并通过 journalctl -u myflaskapp -e 查看日志。

Socket 权限被拒绝

Nginx 用户(www-data)需要读取 home 目录中 socket 文件的权限。将 www-data 加入您的用户组:

sudo usermod -aG YOUR_USERNAME www-data sudo chmod 710 /home/YOUR_USERNAME

生产环境中的 Flask 调试模式

确保 app.py 中未设置 debug=True,且环境变量 FLASK_DEBUG=1 未启用。调试模式会开启 Werkzeug 的交互式调试器,这在生产环境中是严重的安全漏洞。

总结:Python 3 + virtualenv → Flask + Gunicorn → systemd 服务 → Nginx 反向代理 → UFW 防火墙 → Let's Encrypt SSL = VPS 上生产就绪的 Flask 部署。

需要一台 VPS 来运行 Python Flask?

AsiaGB 提供 Linux Ubuntu VPS,起价 ฿500/月 · 完整 Root 权限 · SSD · 1 个独立 IP

查看 VPS 方案 →