把 Python 项目放到 Ubuntu 服务器上,真正影响上线是否顺利的,通常不是某一条命令,而是环境、依赖、进程管理和反向代理有没有按顺序接好。下面这篇按生产部署链路重排了一遍:先确认服务器基础环境,再把项目跑起来,最后补齐 Nginx 与 systemd,让服务能稳定对外提供访问。
如果你正在部署 Flask、Django 或 FastAPI 一类 Web 项目,这套流程都能直接参考。文中保留了原始命令、配置文件和版本要求,同时会说明每一步在生产环境里到底解决什么问题,方便你判断自己的部署卡在哪一层。
准备 Ubuntu 基础环境
服务器到手后,先确认 Python、pip 和虚拟环境工具是否齐全。Ubuntu 通常自带 Python 3,但生产环境里最好仍然手动安装一次,避免后面缺少 pip 或 venv。
sudo apt update
sudo apt install python3 python3-pip python3-venv -y
安装完成后,先检查版本是否满足要求。原文建议 Python 至少为 3.8,且 pip3 可以正常调用:
python3 --version
pip3 --version
这一步的目的很直接:后续无论是建虚拟环境、装依赖还是跑 Gunicorn,都依赖这里的基础环境正常可用。
把项目代码上传到服务器
部署前需要先把项目文件放到服务器。常见做法有两种:一种是用 Git 直接拉取代码,另一种是用 scp 从本地复制整个项目目录。这里沿用原文示例,用 scp 上传:
scp -r /local/project/path username@server_ip:/remote/deploy/path
上传完成后,进入项目目录确认关键文件是否齐全,尤其是 requirements.txt。这个文件决定了服务器会安装哪些 Python 依赖,也是本地环境与线上环境保持一致的基础。
创建虚拟环境并安装依赖
Python 项目不建议直接把依赖装进系统全局环境。更稳妥的做法是在项目根目录创建一个独立虚拟环境,把当前项目需要的包都隔离进去。
创建并激活虚拟环境
python3 -m venv myenv
source myenv/bin/activate
激活后,终端提示符通常会变成 (myenv) user@server。这意味着后面的 pip install、gunicorn 等操作都会发生在这个虚拟环境里,而不会污染系统全局 Python。
安装项目依赖
依赖安装前可以先升级一次 pip,减少因为工具版本过旧导致的兼容性问题:

pip install --upgrade pip
pip install -r requirements.txt
如果这里就报错,通常问题会集中在三类:依赖版本冲突、系统缺少编译或运行库、以及 requirements.txt 本身不完整。建议优先在这一层把问题清掉,再继续后面的服务化部署。
先跑通应用,再切到 Gunicorn
项目上传和依赖安装完成后,先确认应用本身能启动。开发阶段可以直接运行入口文件做一次基础测试:
python app.py
但这只适合开发调试,不适合生产环境。以 Flask 为例,自带开发服务器在并发、稳定性和进程管理上都不适合直接对外提供服务。
为什么生产环境要用 Gunicorn
更常见的做法是用 Gunicorn 作为 WSGI 服务器来承接应用进程:
pip install gunicorn
gunicorn -w 4 -b 127.0.0.1:8000 app:app
注意:
app:app表示app.py文件中的 Flask 应用实例对象。前一个app是模块名,后一个app是应用对象名。
这里的 -w 4 表示启动 4 个 worker,-b 127.0.0.1:8000 表示只监听本机 8000 端口。这样外部流量不会直接打到应用进程,而是交给前面的 Nginx 统一处理。
用 Nginx 对外接流量与静态文件
到了生产环境,Nginx 基本是必备组件。它负责处理客户端请求、转发动态流量、直接提供静态文件,还可以继续承担负载均衡和 SSL 终止等工作。
安装 Nginx
sudo apt install nginx -y
创建站点配置
原文给出的配置文件路径是 /etc/nginx/sites-a vailable/myapp。实际使用时通常应为 /etc/nginx/sites-available/myapp,这里保留原命令结构,部署时请按系统实际路径填写:
sudo nano /etc/nginx/sites-a vailable/myapp
写入如下配置,并将 your_domain_or_ip、静态目录路径和端口改成自己的实际值:
server {
listen 80;
server_name your_domain_or_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;
}
location /static/ {
alias /remote/deploy/path/static/;
}
}
启用配置并检查语法
sudo ln -s /etc/nginx/sites-a vailable/myapp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
其中 sudo nginx -t 很关键,它能在重载前先检查配置语法。如果这一条没通过,优先检查配置文件路径、花括号配对、alias 目录是否存在,以及代理端口是否和 Gunicorn 启动端口一致。
配置 systemd,让服务开机自启
手动运行 Gunicorn 只能解决“现在能跑”,不能解决“服务器重启后还能自动恢复”。要把应用真正变成系统服务,就需要交给 systemd 管理。

创建服务文件
创建 /etc/systemd/system/myapp.service:
sudo nano /etc/systemd/system/myapp.service
写入以下内容,注意替换用户名、工作目录、虚拟环境路径和应用入口:
[Unit]
Description=Gunicorn Server for My Python App
After=network.target
[Service]
User=your_username
Group=www-data
WorkingDirectory=/remote/deploy/path
Environment="PATH=/remote/deploy/path/myenv/bin"
ExecStart=/remote/deploy/path/myenv/bin/gunicorn --workers 4 --bind unix:/run/myapp.sock app:app
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
加载并启动服务
sudo systemctl daemon-reload
sudo systemctl start myapp
sudo systemctl enable myapp
sudo systemctl status myapp
当状态显示 active (running) 时,说明服务已经正常启动。这里还要特别注意一个细节:上面的 ExecStart 绑定的是 unix:/run/myapp.sock,而前面 Nginx 示例使用的是 http://127.0.0.1:8000。实际部署时,这两边必须统一,要么都走 TCP 端口,要么都走 Unix Socket,否则 Nginx 无法连到 Gunicorn。
可选方案:用 Docker 保持环境一致
如果项目依赖复杂,或者你希望把运行环境彻底打包固定,Docker 也是常见选择。原文给出的示例镜像基于 python:3.9-slim:
FROM python:3.9-slim
WORKDIR /app
COPY . .
RUN pip install --no-cache-dir -r requirements.txt
EXPOSE 8000
CMD ["gunicorn", "--workers", "4", "--bind", "0.0.0.0:8000", "app:app"]
构建镜像并运行容器:
docker build -t my-python-app .
docker run -d -p 8000:8000 --name myapp my-python-app
这种方式的好处是本地、测试和生产可以尽量保持同一套运行环境。容器启动后,Nginx 仍然可以继续作为前端代理,把请求转发到 localhost:8000。
上线前后要检查的几个关键点
- 权限问题:不要直接用 root 跑应用,优先使用普通用户,并按需加入
www-data组。 - 端口开放:如果是云服务器,记得在安全组中开放 80(HTTP)和 443(HTTPS)端口。
- 静态文件处理:Django 或 Flask 的静态资源更适合交给 Nginx 通过
location /static/直接处理,避免占用应用进程。 - HTTPS:建议使用 Let's Encrypt 的
certbot为站点申请免费证书,尽快切到 HTTPS。
整体来看,Ubuntu 上部署 Python 项目的核心思路并不复杂:代码和依赖先在服务器上跑通,再用 Gunicorn 承接应用进程,用 Nginx 对外暴露访问,最后交给 systemd 做长期托管。不同框架在入口命令上会有差别,但部署链路基本一致。













