基于 Nginx 和 Python 的 Web 项目部署配置实战
Django 项目部署
核心原理
Django 是 Python 重量级 Web 框架,自带开发服务器仅适用于调试,生产环境需搭配 :
在 Linux 环境下使用 Nginx 配合不同 Python Web 框架(Django、Flask、FastAPI)进行生产环境部署的完整流程。涵盖虚拟环境搭建、WSGI/ASGI 服务器配置(uWSGI、Gunicorn、Uvicorn)、Systemd 服务管理以及 Nginx 反向代理设置。重点讲解静态文件处理、进程管理、日志配置及性能调优技巧,确保应用在高并发场景下的稳定运行。

Django 是 Python 重量级 Web 框架,自带开发服务器仅适用于调试,生产环境需搭配 :
# 更新系统包
apt update && apt -y upgrade
# 安装依赖(编译 uWSGI 需 build-essential/python3-dev)
# python3:安装 Python 3 解释器,提供基础的 Python 运行环境
# python3-pip:安装 Python 3 的包管理工具 pip,用于安装 / 管理 Python 第三方库
# nginx:安装 Nginx 高性能 HTTP 服务器 / 反向代理软件
# build-essential:安装编译源码所需的基础工具集(如 gcc、make 等),用于编译依赖源码的 Python 包(如 uWSGI)
# python3-dev:安装 Python 3 的开发文件(如头文件、库文件),用于编译与 Python 内核交互的扩展模块
# python3.12-venv:安装 Python 3.12 版本的虚拟环境模块,支持创建隔离的 Python 运行环境,避免项目依赖冲突
apt -y install python3 python3-pip nginx build-essential python3-dev python3.12-venv
# 创建项目目录
mkdir -p /data && cd /data
# 创建并激活虚拟环境
python3 -m venv myprojectenv
source myprojectenv/bin/activate
# 激活后终端前缀显示 (myprojectenv)
# 配置 pip 国内源(加速安装)
pip config set global.index-url https://pypi.doubanio.com/simple
pip config set install.trusted-host pypi.doubanio.com
# 安装指定版本 Django(推荐固定版本避免兼容问题)
pip install django==5.2
# 验证安装
django-admin --version
# 输出 5.2 则成功
# 创建项目
django-admin startproject myproject && cd myproject
# 配置允许访问的主机(修改 settings.py)
vim myproject/settings.py
# 修改内容:
ALLOWED_HOSTS = ['10.0.0.13', 'localhost']
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
DEBUG = False # 生产环境关闭调试模式
# 数据库初始化(默认 SQLite,生产建议 MySQL/PostgreSQL)
python manage.py makemigrations # 生成迁移文件(无模型则提示 No changes)
python manage.py migrate # 执行迁移,创建默认表
python manage.py createsuperuser # 创建后台管理员
# 示例:用户名 admin,邮箱 [email protected],密码(建议强密码,弱密码需输入 y 确认)
# 收集静态文件(admin 后台样式等)
python manage.py collectstatic # 确认输入 yes,文件会存入 static 目录
# 虚拟环境内安装 uWSGI
pip install uwsgi==2.0.29
# 验证 uWSGI
uwsgi --version
# 输出 2.0.29 则成功
在 /data/myproject 目录创建 uwsgi.ini,核心配置如下:
[uwsgi]
# Django 项目配置
chdir = /data/myproject # 项目根目录
module = myproject.wsgi:application # WSGI 应用入口
home = /data/myprojectenv # 虚拟环境路径
# 进程管理
master = true # 主进程模式
processes = 5 # 工作进程数(建议 = CPU 核心数 * 2 + 1)
threads = 2 # 每个进程线程数
# 通信方式(Unix Socket 比 TCP 更高效)
socket = /data/myproject/myproject.sock # Socket 文件路径
chmod-socket = 666 # 赋予 Socket 读写权限
vacuum = true # 停止时自动清理 Socket 文件
# 权限控制(避免 root 运行)
uid = www-data # nginx 运行用户
gid = www-data # nginx 运行组
# 日志配置
daemonize = /var/log/uwsgi/myproject.log # 后台运行并输出日志
pidfile = /data/myproject/uwsgi.pid # 进程 PID 文件
创建 /etc/systemd/system/uwsgi.service:
[Unit]
Description=uWSGI Service for Django Project
After=syslog.target network.target # 网络就绪后启动
[Service]
User=www-data
Group=www-data
WorkingDirectory=/data/myproject
ExecStart=/data/myprojectenv/bin/uwsgi --ini /data/myproject/uwsgi.ini
ExecReload=/bin/kill -HUP $MAINPID # 热重载
ExecStop=/bin/kill -INT $MAINPID # 优雅停止
Restart=always # 异常退出自动重启
RestartSec=3 # 重启间隔
KillMode=mixed
[Install]
WantedBy=multi-user.target
启动并验证 uWSGI:
# 创建日志目录并授权
mkdir -p /var/log/uwsgi && chown www-data:www-data /var/log/uwsgi
# 重载 systemd 配置
systemctl daemon-reload
# 启动服务
systemctl start uwsgi
systemctl enable uwsgi # 开机自启
systemctl status uwsgi # 查看状态(active (running) 则成功)
rm -f /etc/nginx/sites-enabled/default # 删除默认站点
创建 /etc/nginx/conf.d/myproject.conf:
server {
listen 80;
server_name 10.0.0.13; # 服务器 IP/域名
# 静态文件处理(Nginx 直接返回,不经过 uWSGI)
location /static/ {
root /data/myproject; # 静态文件根目录
expires 30d; # 缓存 30 天
add_header Cache-Control "public";
}
# 动态请求转发给 uWSGI
location / {
include uwsgi_params; # 加载 uWSGI 通用参数
uwsgi_pass unix:/data/myproject/myproject.sock; # 对接 Socket
uwsgi_connect_timeout 30s; # 连接超时
uwsgi_read_timeout 30s; # 读取超时
}
# 日志配置
access_log /var/log/nginx/myproject_access.log;
error_log /var/log/nginx/myproject_error.log warn;
}
# 检查配置语法
nginx -t # 输出 syntax is ok 则成功
# 启动/重载 Nginx
systemctl restart nginx
systemctl enable nginx # 开机自启
# 验证访问
curl http://10.0.0.13 # 访问 Django 首页
curl http://10.0.0.13/admin # 访问后台管理页(输入 admin 账号密码)
Flask 是轻量级 Web 框架,生产环境使用 Gunicorn(WSGI 服务器)+ Nginx:
# 创建虚拟环境
mkdir -p /data && cd /data
python3 -m venv myflaskenv
source myflaskenv/bin/activate
# 配置 pip 源
pip config set global.index-url https://pypi.doubanio.com/simple
pip config set install.trusted-host pypi.doubanio.com
# 安装 Flask 和 Gunicorn
pip install flask==2.3.3 gunicorn==23.0.0
在 /data/flaskapp 目录创建 app.py:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, Flask!'
@app.route('/user/<name>')
def user(name):
return f'Hello, {name}!'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=False)
# /data/flaskapp/gunicorn.conf.py
bind = '127.0.0.1:5000' # 仅本地监听,通过 Nginx 转发
workers = 4 # 工作进程数
worker_class = 'sync' # 工作模式(高并发可改用 gevent)
max_requests = 1000 # 每个进程最大请求数(避免内存泄漏)
max_requests_jitter = 50 # 随机重启偏移,避免所有进程同时重启
# 日志配置
accesslog = '/var/log/gunicorn/access.log'
errorlog = '/var/log/gunicorn/error.log'
loglevel = 'info'
timeout = 30 # 请求超时时间
创建 /etc/systemd/system/gunicorn.service:
[Unit]
Description=Gunicorn Service for Flask App
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/data/flaskapp
Environment="PATH=/data/myflaskenv/bin"
ExecStart=/data/myflaskenv/bin/gunicorn -c /data/flaskapp/gunicorn.conf.py app:app
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -INT $MAINPID
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
启动 Gunicorn:
mkdir -p /var/log/gunicorn && chown www-data:www-data /var/log/gunicorn
systemctl daemon-reload
systemctl start gunicorn && systemctl enable gunicorn
创建 /etc/nginx/conf.d/flaskapp.conf:
server {
listen 80;
server_name 10.0.0.13;
location / {
proxy_pass http://127.0.0.1:5000; # 转发到 Gunicorn
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_connect_timeout 30s;
proxy_read_timeout 30s;
}
access_log /var/log/nginx/flask_access.log;
error_log /var/log/nginx/flask_error.log warn;
}
验证访问:
nginx -t && systemctl restart nginx
curl http://10.0.0.13 # 输出 Hello, Flask!
curl http://10.0.0.13/user/test # 输出 Hello, test!
FastAPI 是异步 Web 框架,基于 ASGI(异步服务器网关接口),性能远超传统 WSGI 框架:
# 创建虚拟环境
mkdir -p /data && cd /data
python3 -m venv myasgienv
source myasgienv/bin/activate
# 配置 pip 源
pip config set global.index-url https://pypi.doubanio.com/simple
pip config set install.trusted-host pypi.doubanio.com
# 安装 FastAPI 和 Uvicorn
pip install fastapi==0.104.1 uvicorn==0.24.0.post1 asyncio
在 /data/fastapp 目录创建 main.py:
import asyncio
from fastapi import FastAPI
app = FastAPI()
# 同步路由
@app.get("/")
async def read_root():
return {"Hello": "FastAPI"}
# 带参数路由
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}
# 异步任务示例(模拟数据库查询)
async def fake_db_query():
await asyncio.sleep(1) # 模拟 I/O 等待
return {"message": "Data from database"}
@app.get("/db")
async def read_db():
result = await fake_db_query()
return result
# /data/fastapp/uvicorn_config.py
import uvicorn
if __name__ == "__main__":
uvicorn.run("main:app", host="127.0.0.1", # 仅本地监听
port=8000,
log_level="info",
workers=4, # 多进程模式(异步建议 = CPU 核心数)
reload=False # 生产环境关闭自动重载)
创建 /etc/systemd/system/uvicorn.service:
[Unit]
Description=Uvicorn Service for FastAPI App
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/data/fastapp
Environment="PATH=/data/myasgienv/bin"
ExecStart=/data/myasgienv/bin/python /data/fastapp/uvicorn_config.py
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -INT $MAINPID
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
启动 Uvicorn:
systemctl daemon-reload
systemctl start uvicorn && systemctl enable uvicorn
创建 /etc/nginx/conf.d/fastapp.conf:
server {
listen 80;
server_name 10.0.0.13;
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_connect_timeout 60s;
proxy_read_timeout 60s;
}
access_log /var/log/nginx/fastapi_access.log;
error_log /var/log/nginx/fastapi_error.log warn;
}
# 安装 httpie 测试工具
pip install httpie
# 并发测试异步接口(10 个请求并行)
timeseq10 | xargs -I{} -P 10 http GET http://10.0.0.13/db
# 预期输出:实际耗时约 1 秒(异步并行),而非 10 秒(同步串行)
curl http://10.0.0.13 # 输出 {"Hello":"FastAPI"}
curl http://10.0.0.13/items/5?q=test # 输出 {"item_id":5,"q":"test"}
curl http://10.0.0.13/db # 输出 {"message":"Data from database"}
tail -f /var/log/uwsgi/myproject.logtail -f /var/log/nginx/myproject_error.logsystemctl reload uwsgi/gunicorn(热重载,不中断服务)nginx -s reload2*CPU + 1);gzip on;)。
微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online