把 Python 项目部署到 Ubuntu,难点通常不在某一条命令,而在于你是否把“环境、进程、反向代理、开机自启”这几件事按顺序接好了。下面按实际部署流程展开:先准备 Python 运行环境,再用虚拟环境隔离依赖,接着区分开发测试启动和生产启动,最后用 Gunicorn + Systemd + Nginx 组成一套能长期运行的发布方案。
准备 Ubuntu 基础环境
先刷新系统包索引,并安装 Python 运行所需的基础组件。这里保留原始命令,适合在全新 Ubuntu 服务器上直接执行:
sudo apt update
sudo apt install python3 python3-pip python3-venv -y
安装完成后,先确认版本是否正常,尤其是 Python 版本建议在 3.6 以上:
python3 --version
# 确认Python版本(建议3.6+)
pip3 --version # 确认pip版本
如果这一步就报错,后面的虚拟环境、依赖安装和服务启动都会跟着失败,因此建议先把系统层的 Python 与 pip 检查完整。
创建虚拟环境并安装项目依赖
先把项目放进独立虚拟环境
在服务器上跑 Python 项目,尽量不要直接使用系统全局环境。虚拟环境的作用,是让每个项目拥有独立依赖,避免不同项目之间互相覆盖包版本。
cd /path/to/your_project
# 进入项目目录
python3 -m venv myenv # 创建虚拟环境(myenv为环境名称,可自定义)
source myenv/bin/activate # 激活虚拟环境(激活后命令行前缀显示环境名)
⚠️ 注意:后续安装依赖、启动 Gunicorn 等操作,都应在这个虚拟环境中完成。
用 requirements.txt 安装依赖
大多数 Python 项目都会把依赖写在 requirements.txt 中,服务器部署时直接安装即可:
pip install -r requirements.txt
# 安装所有依赖
如果你的项目还没有这个文件,也可以先在当前环境中导出一份:
pip freeze > requirements.txt
# 导出当前环境依赖到文件
这一节完成后,项目至少应具备“能在当前 shell 中启动”的基础条件。
先确认项目能正常运行
正式接入 Gunicorn 和 Nginx 之前,先确认项目本身在服务器环境里能跑起来。不同类型的项目,启动方式并不一样。
普通 Python 脚本
python main.py
Flask 或 Django 的开发测试启动
如果是 Web 项目,可以先用框架自带的开发服务器做一次功能验证,但要注意,这种方式只适合测试,不适合生产环境。
Flask:
flask run
# 或 python app.py(若app.py中有Flask实例)
Django:
python manage.py runserver
如果此时就无法访问页面,优先检查依赖是否装全、环境变量是否缺失、入口文件路径是否正确。先把应用本身跑通,再继续后面的生产配置。
生产环境为什么要换 Gunicorn,并交给 Systemd 托管
用 Gunicorn 替代开发服务器
Flask、Django 自带的开发服务器主要面向调试,不适合承载生产流量。生产环境通常会换成 Gunicorn 这类 WSGI 服务器。

pip install gunicorn
# 安装Gunicorn
以 Flask 项目为例,假设入口对象是 app.py 里的 app,启动命令如下:
gunicorn -w 4 -b 127.0.0.1:8000 app:app
# -w指定工作进程数,-b指定绑定地址
这里的 -w 4 表示 4 个 worker,-b 127.0.0.1:8000 表示仅监听本机 8000 端口,通常用于先验证 Gunicorn 是否能正确加载应用。
注册成 Systemd 服务
如果只在 shell 里手动启动 Gunicorn,一旦终端断开或服务器重启,服务就会中断。更稳妥的做法是把它注册成 Systemd 服务。
sudo nano /etc/systemd/system/myapp.service
# 创建服务文件
服务文件内容如下,路径、用户名和应用入口都需要按你的实际项目替换:
[Unit]
Description=Gunicorn Server for My Python App
After=network.target
[Service]
User=ubuntu
# 替换为你的系统用户
Group=www-data
WorkingDirectory=/path/to/your_project
ExecStart=/path/to/your_project/myenv/bin/gunicorn --workers 4 --bind unix:/run/myapp.sock app:app
Restart=always
[Install]
WantedBy=multi-user.target
保存后执行:
sudo systemctl daemon-reload
sudo systemctl start myapp
sudo systemctl enable myapp
# 设置开机自启
这里的关键点是 ExecStart:它直接指定虚拟环境中的 Gunicorn,并将服务绑定到 unix:/run/myapp.sock。后面 Nginx 会通过这个 Unix socket 转发请求。
配置 Nginx 反向代理对外提供访问
Gunicorn 负责运行 Python 应用,Nginx 负责接收外部 HTTP 请求、转发到 Gunicorn,并可顺手处理静态文件。这是 Ubuntu 上最常见的一套组合。
安装并编写 Nginx 配置
sudo apt install nginx -y
# 安装Nginx
创建或修改站点配置文件:
sudo nano /etc/nginx/sites-a vailable/myapp
配置内容如下:
server {
listen 80;
server_name your_domain_or_ip;
# 替换为你的域名或服务器IP
location / {
include proxy_params;
proxy_pass http://unix:/run/myapp.sock;
# 转发到Gunicorn的Unix socket
}
# 可选:配置静态文件目录(需在Django/Flask中设置STATIC_ROOT)
location /static/ {
alias /path/to/your_project/static/;
# 替换为静态文件目录
}
}
这段配置的作用很直接:所有根路径请求先进入 Nginx,再由 Nginx 通过 /run/myapp.sock 转发给 Gunicorn;如果项目有静态资源,还可以单独映射 /static/。
启用配置并检查语法
sudo ln -s /etc/nginx/sites-a vailable/myapp /etc/nginx/sites-enabled/
# 创建符号链接
sudo nginx -t
# 测试配置语法
sudo systemctl restart nginx
# 重启Nginx
其中 sudo nginx -t 很重要。只有语法检查通过,再重启 Nginx,才能避免因为配置错误导致网站直接不可用。
放行端口、验证部署并查看日志
UFW 防火墙放行 HTTP/HTTPS
如果服务器启用了 UFW,需要把 Web 服务端口放行,否则外部仍然访问不到。

sudo ufw allow 'Nginx Full'
# 允许HTTP和HTTPS
sudo ufw enable
# 启用防火墙(若未启用)
部署完成后如何检查是否成功
浏览器访问 http://your_domain_or_ip,如果能看到应用页面,说明整体链路已经打通。
如果页面打不开,可以按下面的顺序排查:
- 检查 Nginx 状态:
sudo systemctl status nginx - 检查 Gunicorn 状态:
sudo systemctl status myapp - 查看应用日志:
journalctl -u myapp -f(实时日志)或/var/log/nginx/error.log(Nginx 错误日志)
通常来说,访问失败无非是三类问题:应用没起来、Nginx 没转发对、或者防火墙和端口没放通。按这个顺序查,定位会快很多。
可选优化:HTTPS、并发参数与日志管理
给站点补上 HTTPS
如果项目需要正式对外提供服务,建议尽快配置 SSL 证书。原文给出的方案是使用 Let's Encrypt 和 Certbot:
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d your_domain.com
# 替换为你的域名
再看 Gunicorn 参数和日志轮转
除了 HTTPS,还有两个常见优化点:
- 性能调优:根据服务器 CPU 核心数调整 Gunicorn 的
workers数量,通常设置为 CPU 核心数的 2-4 倍。 - 日志管理:配置日志轮转,例如使用
logrotate,避免日志文件持续增长占满磁盘。
做到这里,一套完整的 Ubuntu 部署流程就基本成型了:Python 环境负责运行,虚拟环境负责隔离依赖,Gunicorn 负责承载应用,Systemd 负责守护进程,Nginx 负责对外服务,UFW 与 HTTPS 则负责访问控制和传输安全。













