华为云ECS云服务器部署Django网站:uWSGI+Nginx全套配置实战指南
一、为什么选择Nginx+uWSGI部署Django
Django虽然自带了开发服务器(python manage.py runserver),但该服务器仅适用于开发调试,不具备生产环境所需的并发处理能力、安全性和稳定性。将Django应用部署至生产环境,需要借助专业的应用服务器与Web服务器构建分层架构。
uWSGI是一个实现了WSGI协议的Web服务器,它负责将Nginx转发的请求翻译成Django项目能够处理的格式,并调用Django的WSGI接口执行业务逻辑。Nginx则作为反向代理服务器置于uWSGI前端,负责处理静态资源请求、负载均衡、SSL终止以及抵御部分恶意流量。这种分层架构具备三大核心优势:Nginx高效处理静态资源实现动静分离,uWSGI专注运行Python应用提升动态请求处理效率,二者协同工作可显著提升整体服务的并发能力与稳定性。
需要先登录华为云控制台,点击:华为云控制台,还没有账号,点击:注册并关联,已有账号点击:登录后关联
二、部署前的准备工作
2.1 华为云ECS选购与配置建议
在华为云控制台购买弹性云服务器(ECS)时,建议根据项目规模选择合适的配置。对于小型个人博客或演示项目,1核2GB的配置即可运行;生产环境建议不低于2核4GB。操作系统方面,华为云官方推荐CentOS 7/8、Ubuntu 22/10/18或Huawei Cloud EulerOS 2.0。本文以Ubuntu 22.04 LTS为例进行演示。
购买完成后,需要为ECS绑定弹性公网IP(EIP),以便后续通过公网访问部署好的网站。
2.2 安全组规则配置
安全组是华为云的重要网络安全隔离手段,需要在安全组中放行必要的端口。部署Django网站至少需要开放以下入方向端口:
- TCP 22:SSH远程登录端口
- TCP 80:HTTP网站访问端口
- TCP 8001-8003:uWSGI测试与调试端口(可选)
配置方法:登录华为云控制台,进入“虚拟私有云 VPC” → “安全组” → 选择ECS所在的安全组 → “入方向规则” → “添加规则”,按上述端口列表逐一添加。
2.3 更新镜像源
为了更好地获取和更新系统软件,建议将镜像源更新为华为云镜像源,可显著提升软件包的下载速度。Ubuntu系统执行以下命令:
sudo apt update
sudo apt upgrade -y三、Python环境搭建
3.1 检查Python版本
首先确认ECS自带的Python版本是否与本地Django项目兼容。
which python3
python3 --version如果版本不匹配,需要安装指定版本的Python。以Python 3.10为例:
sudo apt install build-essential libssl-dev zlib1g-dev libncurses5-dev \
libgdbm-dev libnss3-dev libreadline-dev libffi-dev -y
wget https://www.python.org/ftp/python/3.10.12/Python-3.10.12.tgz
tar -xzvf Python-3.10.12.tgz
cd Python-3.10.12
./configure --enable-optimizations
sudo make -j$(nproc)
sudo make install3.2 创建Python虚拟环境
强烈建议为Django项目创建独立的Python虚拟环境,避免依赖冲突。
# 安装venv模块
sudo apt install python3-venv -y
# 创建项目目录并进入
sudo mkdir -p /var/www/myproject
cd /var/www/myproject
# 创建虚拟环境
sudo python3 -m venv venv
# 激活虚拟环境
source venv/bin/activate四、安装与配置uWSGI
4.1 安装uWSGI
在激活的虚拟环境中使用pip安装uWSGI:
pip install uwsgi如果需要在系统全局安装,可使用sudo pip3 install uwsgi。安装完成后可通过以下命令验证:
uwsgi --version4.2 测试uWSGI运行
在正式部署Django项目之前,先用一个简单的测试程序验证uWSGI能否正常运行。
# 创建测试目录
sudo mkdir -p /home/myblog
cd /home/myblog
# 创建测试文件test.py
sudo vim test.py在test.py中输入以下内容:
def application(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return [b"Hello World from uWSGI!"]然后启动uWSGI测试服务:
# Ubuntu系统
uwsgi --http :8001 --wsgi-file test.py
# CentOS系统
sudo /usr/local/bin/uwsgi --http :8001 --wsgi-file test.py在浏览器中访问 http://服务器IP地址:8001,如果看到"Hello World from uWSGI!"页面,说明uWSGI安装成功。
4.3 编写uWSGI配置文件
测试通过后,需要为Django项目编写uWSGI的正式配置文件uwsgi.ini,存放在项目根目录下。
# 进入项目目录
cd /var/www/myproject
# 创建uwsgi.ini配置文件
sudo vim uwsgi.ini以下是完整的uwsgi.ini配置示例:
[uwsgi]
# Django项目的WSGI模块路径
module = myproject.wsgi:application
# 项目工作目录(Django项目根目录)
chdir = /var/www/myproject
# 使用Unix Socket与Nginx通信(推荐方式)
socket = /var/www/myproject/myproject.sock
# Socket文件权限
chmod-socket = 666
# 也可以使用TCP端口方式(备选)
# socket = 127.0.0.1:9001
# 主进程模式
master = true
# 进程数(建议设置为CPU核心数)
processes = 4
# 每个进程的线程数
threads = 2
# 启用多线程
enable-threads = true
# 后台运行并记录日志
daemonize = /var/www/myproject/uwsgi.log
# PID文件,便于管理进程
pidfile = /var/www/myproject/uwsgi.pid
# 设置环境变量
env = DJANGO_SETTINGS_MODULE=myproject.settings
# 超时设置(秒)
http-timeout = 86400
# 进程优雅重启
vacuum = true配置要点说明:
- socket:使用Unix Socket方式与Nginx通信,性能优于TCP端口方式
- processes:通常设置为服务器CPU核心数,可根据实际负载调整
- daemonize:将uWSGI日志写入指定文件,便于后续排查问题
- vacuum:进程退出时自动清理Socket文件
4.4 启动uWSGI服务
# 使用配置文件启动
uwsgi --ini uwsgi.ini
# 查看uWSGI进程状态
ps aux | grep uwsgi
# 停止uWSGI服务
uwsgi --stop uwsgi.pid
# 重启uWSGI服务
uwsgi --reload uwsgi.pid五、安装与配置Nginx
5.1 安装Nginx
在Ubuntu系统中使用apt安装Nginx:
sudo apt install nginx -y
# 启动Nginx服务
sudo systemctl start nginx
# 设置Nginx开机自启
sudo systemctl enable nginx
# 查看Nginx服务状态
sudo systemctl status nginx如果状态显示 Active: active (running),表示Nginx已成功启动。
5.2 配置Nginx虚拟主机
Nginx的配置文件位于 /etc/nginx/sites-available/ 目录。为Django项目创建一个独立的配置文件:
sudo vim /etc/nginx/sites-available/myproject以下是完整的Nginx配置示例:
server {
# 监听端口
listen 80;
listen [::]:80;
# 服务器域名或IP(替换为你的实际域名或IP)
server_name your-domain.com www.your-domain.com;
# 如果没有域名,可使用IP地址
# server_name 你的ECS公网IP;
# 项目根目录
root /var/www/myproject;
# 字符集
charset utf-8;
# 访问日志
access_log /var/log/nginx/myproject_access.log;
error_log /var/log/nginx/myproject_error.log;
# 静态文件处理(动静分离)
location /static/ {
alias /var/www/myproject/static/;
expires 30d;
}
# 媒体文件处理
location /media/ {
alias /var/www/myproject/media/;
expires 30d;
}
# 动态请求转发至uWSGI
location / {
include /etc/nginx/uwsgi_params;
uwsgi_pass unix:/var/www/myproject/myproject.sock;
# 如果使用TCP端口方式,则改为:
# uwsgi_pass 127.0.0.1:9001;
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
}
# 禁止访问敏感文件
location ~* \.(py|pyc|sqlite3|db)$ {
deny all;
}
}配置要点说明:
- server_name:填写你的域名或ECS公网IP
- location /static/ 和 location /media/:实现动静分离,静态文件由Nginx直接处理,无需经过uWSGI
- uwsgi_pass:指定与uWSGI通信的Unix Socket路径,必须与
uwsgi.ini中的socket配置一致 - include uwsgi_params:加载Nginx自带的uWSGI参数文件
5.3 启用站点配置
# 创建符号链接启用站点
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled/
# 测试Nginx配置文件语法
sudo nginx -t
# 如果测试通过,重新加载Nginx配置
sudo systemctl reload nginx六、Django项目生产环境配置
6.1 上传Django项目代码
将本地开发完成的Django项目上传到ECS服务器。常用的方式有:
- 使用
scp命令直接上传 - 使用Git从代码仓库克隆
- 使用华为云CodeArts部署模板自动化部署
以scp方式为例:
# 在本地执行(将本地项目压缩后上传)
tar -czf myproject.tar.gz myproject/
scp myproject.tar.gz root@你的ECS公网IP:/var/www/
# 在ECS上解压
cd /var/www
tar -xzf myproject.tar.gz6.2 安装项目依赖
# 激活虚拟环境
cd /var/www/myproject
source venv/bin/activate
# 安装依赖(确保本地已生成requirements.txt)
pip install -r requirements.txt6.3 修改Django设置
编辑 settings.py 文件,进行生产环境配置:
sudo vim /var/www/myproject/myproject/settings.py关键配置项:
# 生产环境必须关闭DEBUG模式
DEBUG = False
# 允许访问的域名或IP
ALLOWED_HOSTS = ['your-domain.com', 'www.your-domain.com', '你的ECS公网IP']
# 静态文件收集目录
STATIC_ROOT = '/var/www/myproject/static/'
# 媒体文件目录
MEDIA_ROOT = '/var/www/myproject/media/'
# 数据库配置(根据实际情况修改)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'myproject',
'USER': 'myuser',
'PASSWORD': 'your_password',
'HOST': 'localhost',
'PORT': '5432',
}
}
# 安全设置(生产环境强烈建议启用)
SECURE_SSL_REDIRECT = False # 如启用HTTPS则设为True
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True6.4 收集静态文件
Django的静态文件(CSS、JS、图片等)需要通过 collectstatic 命令统一收集到 STATIC_ROOT 指定的目录:
# 确保虚拟环境已激活
cd /var/www/myproject
source venv/bin/activate
python manage.py collectstatic --noinput执行后,所有静态文件将被复制到 /var/www/myproject/static/ 目录,由Nginx直接提供服务。
6.5 数据库迁移
python manage.py makemigrations
python manage.py migrate6.6 创建超级用户
python manage.py createsuperuser七、Systemd服务托管
为了便于管理uWSGI服务的启动、停止、重启和开机自启,建议使用Systemd将其托管为系统服务。
7.1 创建uWSGI服务文件
sudo vim /etc/systemd/system/uwsgi.service写入以下内容(注意替换路径和用户):
[Unit]
Description=uWSGI service for Django project
After=network.target
[Service]
Type=forking
User=www-data
Group=www-data
WorkingDirectory=/var/www/myproject
Environment="PATH=/var/www/myproject/venv/bin"
ExecStart=/var/www/myproject/venv/bin/uwsgi --ini /var/www/myproject/uwsgi.ini
ExecStop=/var/www/myproject/venv/bin/uwsgi --stop /var/www/myproject/uwsgi.pid
ExecReload=/var/www/myproject/venv/bin/uwsgi --reload /var/www/myproject/uwsgi.pid
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target7.2 启动并启用服务
# 重新加载Systemd配置
sudo systemctl daemon-reload
# 启动uWSGI服务
sudo systemctl start uwsgi
# 设置开机自启
sudo systemctl enable uwsgi
# 查看服务状态
sudo systemctl status uwsgi八、部署验证与测试
8.1 验证部署结果
完成所有配置后,在浏览器中访问 http://你的ECS公网IP 或 http://your-domain.com,应该能看到Django网站的首页。
如果访问出现502 Bad Gateway错误,通常表示uWSGI服务未正常启动或Nginx与uWSGI通信失败。可通过以下步骤排查:
# 检查uWSGI服务状态
sudo systemctl status uwsgi
# 查看uWSGI日志
sudo tail -f /var/www/myproject/uwsgi.log
# 查看Nginx错误日志
sudo tail -f /var/log/nginx/myproject_error.log
# 检查Socket文件是否存在
ls -la /var/www/myproject/myproject.sock8.2 常见问题与解决方案
- 问题1:Nginx无法连接uWSGI的Socket
解决方案:确保uwsgi.ini中的socket路径与Nginx配置中的uwsgi_pass路径完全一致,且Socket文件具有正确的读写权限(chmod-socket = 666)。 - 问题2:静态文件无法加载(404错误)
解决方案:确认已执行python manage.py collectstatic,并检查Nginx配置中location /static/的alias路径是否正确指向STATIC_ROOT。 - 问题3:ALLOWED_HOSTS配置错误导致400错误
解决方案:在settings.py中正确配置ALLOWED_HOSTS,包含所有用于访问网站的域名和IP地址。 - 问题4:端口80无法访问
解决方案:检查华为云安全组是否已放行TCP 80端口,并确认Nginx正在监听80端口。
九、部署架构全景回顾
至此,完整的Nginx + uWSGI + Django部署架构已搭建完毕。整个请求链路如下:
- 用户的HTTP请求到达ECS服务器的80端口
- Nginx接收请求,判断是否为静态资源(
/static/或/media/) - 静态资源由Nginx直接返回,动态请求通过
uwsgi_pass转发给uWSGI - uWSGI通过WSGI协议调用Django项目的
wsgi.py入口文件 - Django执行业务逻辑后返回响应,经uWSGI和Nginx逐层返回给用户
这种分层架构充分发挥了Nginx处理高并发静态请求的能力和uWSGI运行Python应用的专业性,是Django生产环境部署的成熟方案。
十、运维建议与扩展方向
- 日志监控:定期查看
/var/log/nginx/和项目目录下的uwsgi.log,及时发现异常 - 进程守护:已通过Systemd实现了uWSGI进程守护和开机自启,确保服务稳定运行
- HTTPS配置:生产环境建议使用Let's Encrypt免费证书配置HTTPS,保障数据传输安全
- 负载均衡:当流量增大时,可配置Nginx进行多台ECS的负载均衡,或增加uWSGI的
processes数量 - 代码更新:更新代码后,需要重新执行
collectstatic并重启uWSGI服务(sudo systemctl restart uwsgi)
常见问题解答
问1:部署完成后访问网站出现502 Bad Gateway,是什么原因?
答:502错误通常表示Nginx无法连接到uWSGI服务。首先检查uWSGI服务是否正常运行(sudo systemctl status uwsgi),然后查看uWSGI日志(tail -f /var/www/myproject/uwsgi.log)排查具体错误。常见原因包括:uWSGI未启动、Socket路径配置不一致、Socket文件权限不足等。
问2:Nginx和uWSGI之间使用Unix Socket和TCP端口有什么区别?
答:Unix Socket基于文件系统进行进程间通信,性能更高、开销更小,适合Nginx和uWSGI部署在同一台服务器上的场景。TCP端口方式支持跨主机通信,适用于分布式部署场景。在单机部署中,推荐使用Unix Socket方式。
问3:修改了Django代码后如何让改动生效?
答:Django代码更新后,需要重启uWSGI服务才能使改动生效。执行 sudo systemctl restart uwsgi 即可。如果修改涉及静态文件(CSS、JS等),还需要重新执行 python manage.py collectstatic 收集更新后的静态文件。
问4:如何配置HTTPS让网站支持加密访问?
答:可以使用Let's Encrypt免费证书配合Certbot工具自动申请和配置HTTPS。安装Certbot后执行 certbot --nginx -d your-domain.com,Certbot会自动修改Nginx配置启用HTTPS并设置自动续期。
问5:uWSGI的processes和threads应该设置多少合适?
答:processes 建议设置为服务器CPU核心数,threads 建议设置为2-4。例如4核CPU可配置 processes=4, threads=2,即总共8个工作线程。具体数值需根据实际负载和响应时间进行调优。
问6:部署后Django的Admin后台无法加载样式,怎么办?
答:这是典型的静态文件未正确收集的问题。确保在 settings.py 中正确设置了 STATIC_ROOT,并执行了 python manage.py collectstatic。同时检查Nginx配置中 location /static/ 的路径是否指向 STATIC_ROOT 目录。



