阿里云Linux云服务器使用Nginx+uWSGI部署Django项目全攻略
前言:为什么选择Nginx+uWSGI部署Django
Django框架自带的开发服务器`python manage.py runserver`仅适用于开发和调试阶段,它性能有限、不具备并发处理能力,且存在安全风险。在生产环境中,需要将Django应用部署到专业的应用服务器上,并配合反向代理服务器实现动静分离、负载均衡和高并发处理。
Nginx与uWSGI的组合是目前部署Django项目的主流方案之一。Nginx作为高性能的HTTP服务器和反向代理服务器,负责处理静态资源请求、负载均衡和SSL终止等任务。uWSGI则是一个实现了WSGI协议的应用服务器,作为Nginx与Django应用之间的桥梁,负责运行Python代码并处理动态请求。这种分层架构能够充分发挥各自优势,提升服务的整体性能和稳定性。
本文将以阿里云ECS(Elastic Compute Service)为例,详细讲解从零开始部署Django项目的全过程。无论你是刚接触云部署的新手,还是希望系统梳理部署流程的开发者,本文都能提供可落地的操作指南。
一、整体架构与工作原理
在开始动手之前,先理解整个架构的请求流转过程。
用户通过浏览器访问网站,请求到达服务器后,首先由Nginx接收。Nginx会判断请求类型:如果请求的是静态资源(如CSS样式表、JavaScript脚本、图片等),Nginx直接从服务器本地文件系统中读取并返回,这一过程不经过Django应用,因此响应速度极快。如果请求的是动态内容(如API接口、页面渲染等),Nginx则将请求通过uWSGI协议转发给uWSGI服务器。uWSGI接收到请求后,将其传递给Django应用进行处理——Django执行相应的业务逻辑(如数据库查询、模板渲染等),生成响应数据后返回给uWSGI,再由uWSGI回传给Nginx,最终由Nginx将响应返回给用户浏览器。
这一架构的核心优势在于“动静分离”。Nginx处理静态文件的能力极为出色,而Django只需专注于动态业务逻辑,两者各司其职,互不干扰,大大降低了Django应用的负载,提升了整体并发处理能力。
二、准备工作:创建阿里云ECS实例
2.1 购买ECS实例
需要先登录阿里云控制台,点击:阿里云控制台,进入ECS产品页面购买实例。
实例配置方面,官方推荐至少选择2 vCPU和4 GiB内存的规格。如果项目规模较小或仅用于测试,1核2GB的配置也可运行,但生产环境建议不低于上述推荐配置。操作系统建议选择Alibaba Cloud Linux 3、CentOS 7.x或Ubuntu 20.04/22.04。本文以Alibaba Cloud Linux 3为例进行演示。
网络配置方面,需为实例分配公网IPv4地址。如果实例创建时未分配公网IP,后续也可绑定弹性公网IP(EIP)。安全组方面,建议新建安全组并至少放行以下端口:22(SSH)、80(HTTP)、443(HTTPS,如需启用)、以及uWSGI与Nginx通信所需的端口(本文使用Unix Socket方式,无需额外开放端口)。如果使用TCP端口通信方式,则需放行对应端口。
2.2 安全组配置要点
安全组是阿里云的重要网络安全隔离机制,相当于云服务器的“虚拟防火墙”。在ECS控制台 → 实例 → 安全组 → 配置规则中,可以添加入方向规则。安全建议:22端口的授权对象尽量限制为个人的IP地址范围,避免暴露给全网。80和443端口根据实际需要开放。如果使用了弹性公网IP,还需确保安全组规则与网络ACL配置协调一致。
三、服务器端环境搭建
3.1 连接服务器
使用SSH客户端(如终端、Putty、MobaXterm等)连接ECS实例:
ssh root@你的服务器公网IP
如果使用的是非root用户,请确保该用户具有sudo权限。
3.2 更新系统与安装基础依赖
连接成功后,首先更新系统软件包并安装基础开发工具:
# Alibaba Cloud Linux / CentOS 系统 yum update -y yum groupinstall -y "Development tools" yum install -y zlib-devel bzip2-devel pcre-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc make
对于Ubuntu系统,使用apt命令:
apt update -y apt install -y build-essential libssl-dev libffi-dev libbz2-dev libreadline-dev libsqlite3-dev zlib1g-dev
3.3 安装Python环境
Alibaba Cloud Linux 3默认已安装Python 3,可通过以下命令确认版本:
which python3 python3 --version
如果系统未安装Python 3或版本过低,建议从源码编译安装Python 3.10或更高版本:
cd /usr/local/src wget https://www.python.org/ftp/python/3.10.13/Python-3.10.13.tgz tar -xzf Python-3.10.13.tgz cd Python-3.10.13 ./configure --enable-optimizations --prefix=/usr/local/python3 make -j $(nproc) make altinstall
安装完成后,创建软链接以便全局使用:
ln -s /usr/local/python3/bin/python3.10 /usr/bin/python3 ln -s /usr/local/python3/bin/pip3.10 /usr/bin/pip3
3.4 安装Nginx
默认软件源的Nginx版本可能较旧,存在安全风险。建议添加Nginx官方源以安装最新稳定版本:
# 添加Nginx官方源(适用于CentOS/Alibaba Cloud Linux) sudo tee /etc/yum.repos.d/nginx.repo
Ubuntu系统可直接使用apt安装,或添加官方源后安装。安装完成后启动Nginx并设置开机自启:
sudo systemctl start nginx sudo systemctl enable nginx
访问服务器公网IP的80端口,如果看到Nginx欢迎页面,说明安装成功。
3.5 安装uWSGI
使用pip安装uWSGI:
pip3 install uwsgi
如果编译过程中出现错误,可能需要先安装Python开发头文件:
yum install -y python3-devel # CentOS/Alibaba Cloud Linux apt install -y python3-dev # Ubuntu
验证uWSGI是否安装成功:
uwsgi --version
四、部署Django项目
4.1 创建项目目录与虚拟环境
良好的项目目录结构有助于后续管理和维护:
sudo mkdir -p /srv/django-app/{logs,static,media}
sudo mkdir -p /run/uwsgi
sudo chown -R $USER:$USER /srv/django-app /run/uwsgi推荐使用Python虚拟环境来隔离项目依赖,避免不同项目间的包版本冲突。安装virtualenv并创建虚拟环境:
pip3 install virtualenv cd /srv/django-app virtualenv venv --python=python3 source venv/bin/activate
进入虚拟环境后,后续的pip安装都将隔离在该环境中。
4.2 创建Django项目(或上传已有项目)
如果是全新项目,可使用django-admin创建示例项目:
django-admin startproject myproject /srv/django-app/
如果已有本地开发完成的Django项目,可通过scp、rsync或Git等方式将项目文件上传至服务器的`/srv/django-app/`目录。上传前建议排除虚拟环境、pyc文件等不必要的文件。
4.3 安装项目依赖
在虚拟环境中安装项目所需的所有依赖包。如果项目根目录下有`requirements.txt`文件:
pip install -r requirements.txt
如果没有,可手动安装Django和uWSGI(uWSGI已在全局安装,但虚拟环境中也建议安装以便统一管理):
pip install django uwsgi
建议使用阿里云PyPI镜像加速下载:
pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple
4.4 配置Django生产环境设置
编辑项目的`settings.py`文件,进行生产环境配置:
vim /srv/django-app/myproject/settings.py
关键配置项如下:
# 关闭调试模式,防止泄露敏感信息
DEBUG = False
# 设置允许访问的主机名或IP,务必包含你的域名或公网IP
ALLOWED_HOSTS = ['你的域名或公网IP']
# 指定静态文件收集目录
STATIC_ROOT = BASE_DIR / 'static'
# 如果使用MySQL/PostgreSQL等生产数据库,替换默认的SQLite配置
# Django默认使用SQLite3,该配置不适用于生产环境
# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.postgresql',
# 'NAME': 'your_db_name',
# 'USER': 'your_db_user',
# 'PASSWORD': 'your_db_password',
# 'HOST': 'localhost',
# 'PORT': '5432',
# }
# }需要注意,当`DEBUG = False`时,Django必须配置`ALLOWED_HOSTS`,否则应用将无法启动。这是Django的内置安全机制,用于防范CSRF等攻击。
4.5 收集静态文件与数据库迁移
执行静态文件收集命令,将项目中的静态文件集中到`STATIC_ROOT`目录,供Nginx直接提供服务:
python /srv/django-app/manage.py collectstatic --noinput
执行数据库迁移,初始化数据库表结构:
python /srv/django-app/manage.py migrate
如果项目使用了自定义数据库,请确保数据库服务已安装并运行,且数据库连接信息配置正确。
五、配置uWSGI应用服务器
5.1 创建uWSGI配置文件
在项目目录下创建uWSGI配置文件,例如`uwsgi.ini`:
vim /srv/django-app/uwsgi.ini
以下是一个完整的uWSGI配置示例:
[uwsgi] # 项目根目录(包含manage.py的目录) chdir = /srv/django-app # Django项目的WSGI模块(项目名.wsgi) module = myproject.wsgi # 虚拟环境路径 home = /srv/django-app/venv # 使用Unix Socket与Nginx通信(推荐,性能优于TCP端口) socket = /run/uwsgi/django.sock # Socket文件权限 chmod-socket = 666 # 主进程模式 master = true # 工作进程数量(通常为CPU核心数) workers = 4 # 每个工作进程的线程数 threads = 2 # 请求上限,防止内存泄漏 max-requests = 5000 # 优雅退出时清理socket文件 vacuum = true # 后台运行并指定日志文件 daemonize = /srv/django-app/logs/uwsgi.log # 进程ID文件 pidfile = /srv/django-app/logs/uwsgi.pid # 设置环境变量 env = DJANGO_SETTINGS_MODULE=myproject.settings # 缓冲区大小(适用于大请求) buffer-size = 32768
上述配置中,`chdir`指定项目根目录,`module`指定WSGI模块。如果项目虚拟环境不在默认位置,需通过`home`参数指定。`socket`指定了与Nginx通信的Unix Socket文件路径。
关于`lazy-apps`参数:如果设置为true,uWSGI会在每个工作进程启动后再加载应用程序,这有助于避免一些内存共享问题,但会增加启动时间。根据项目实际情况决定是否启用。
5.2 测试uWSGI是否能正常运行
可以先通过命令行测试uWSGI能否正常启动Django项目:
cd /srv/django-app source venv/bin/activate uwsgi --ini uwsgi.ini
查看日志文件确认是否有错误:
tail -f /srv/django-app/logs/uwsgi.log
如果日志中没有报错信息,说明uWSGI配置正确。可以通过`netstat -an | grep .sock`或`ls -la /run/uwsgi/`确认socket文件是否已生成。
六、配置Nginx反向代理
6.1 创建Nginx站点配置文件
Nginx的配置文件通常位于`/etc/nginx/conf.d/`或`/etc/nginx/sites-available/`目录下。在`/etc/nginx/conf.d/`中创建Django项目的配置文件:
vim /etc/nginx/conf.d/django.conf
以下是一个完整的Nginx配置示例:
server {
listen 80;
server_name 你的域名或公网IP;
# 字符集
charset utf-8;
# 客户端上传文件大小限制
client_max_body_size 75M;
# 日志配置
access_log /srv/django-app/logs/nginx_access.log;
error_log /srv/django-app/logs/nginx_error.log;
# 静态文件路径(由Django的collectstatic收集)
location /static/ {
alias /srv/django-app/static/;
expires 30d;
}
# 媒体文件路径(用户上传的文件)
location /media/ {
alias /srv/django-app/media/;
expires 30d;
}
# 动态请求转发给uWSGI
location / {
include uwsgi_params;
uwsgi_pass unix:/run/uwsgi/django.sock;
uwsgi_read_timeout 300;
uwsgi_send_timeout 300;
uwsgi_connect_timeout 60;
}
# 健康检查路径(可选)
location /health/ {
return 200 "healthy\n";
add_header Content-Type text/plain;
}
}关键配置说明:
`location /static/`和`location /media/`分别映射Django的静态文件和用户上传的媒体文件,由Nginx直接提供服务。
`location /`中的`uwsgi_pass`必须与uWSGI配置文件中的`socket`路径保持一致。
`include uwsgi_params`引入Nginx自带的uWSGI参数文件,其中定义了标准的uWSGI协议参数。
`server_name`应替换为实际的域名或公网IP。
6.2 测试并重启Nginx
检查Nginx配置文件语法是否正确:
nginx -t
如果显示`Syntax is OK`和`test is successful`,则配置无误。重启Nginx使配置生效:
systemctl restart nginx
七、启动服务与验证
7.1 启动uWSGI
以守护进程方式启动uWSGI(使用`-d`参数或配置文件中已设置`daemonize`):
cd /srv/django-app source venv/bin/activate uwsgi --ini uwsgi.ini
查看uWSGI是否正常运行:
ps aux | grep uwsgi
7.2 访问验证
在浏览器中输入服务器的公网IP或已解析的域名,应该能看到Django应用的首页。如果页面无法访问,按以下顺序排查:
检查安全组是否放行了80端口。
检查Nginx和uWSGI服务是否都在运行。
查看Nginx错误日志(`/srv/django-app/logs/nginx_error.log`)和uWSGI日志(`/srv/django-app/logs/uwsgi.log`)。
检查`ALLOWED_HOSTS`是否包含当前访问的域名或IP。
八、进程管理与开机自启
8.1 使用Supervisor管理uWSGI进程
在生产环境中,建议使用进程管理工具(如Supervisor)来管理uWSGI进程,实现自动重启和开机自启。
安装Supervisor:
pip3 install supervisor
生成默认配置文件:
echo_supervisord_conf > /etc/supervisord.conf
在配置文件末尾添加uWSGI的程序配置:
[program:django] command=/srv/django-app/venv/bin/uwsgi --ini /srv/django-app/uwsgi.ini directory=/srv/django-app autostart=true autorestart=true stderr_logfile=/srv/django-app/logs/supervisor_err.log stdout_logfile=/srv/django-app/logs/supervisor_out.log user=root stopasgroup=true killasgroup=true
启动Supervisor:
supervisord -c /etc/supervisord.conf supervisorctl start django supervisorctl status
8.2 设置Supervisor开机自启
创建systemd服务文件`/etc/systemd/system/supervisord.service`:
[Unit] Description=Supervisor process control system After=network.target [Service] Type=forking ExecStart=/usr/local/bin/supervisord -c /etc/supervisord.conf ExecStop=/usr/local/bin/supervisorctl shutdown ExecReload=/usr/local/bin/supervisorctl reload KillMode=process Restart=on-failure RestartSec=42s [Install] WantedBy=multi-user.target
启用开机自启:
systemctl enable supervisord systemctl start supervisord
九、域名绑定与SSL证书配置
9.1 域名解析
在阿里云控制台的域名解析服务中,添加A记录将域名指向ECS实例的公网IP。解析生效后,即可通过域名访问Django应用。
9.2 申请SSL证书
阿里云提供免费的DV SSL证书。在控制台搜索“SSL证书”,进入证书管理页面,点击“免费证书”进行申请。填写需要绑定的域名,完成域名验证后即可下载证书文件。
9.3 配置Nginx支持HTTPS
将证书文件上传到服务器(如`/etc/nginx/ssl/`目录),修改Nginx配置文件启用HTTPS:
server {
listen 443 ssl http2;
server_name 你的域名;
ssl_certificate /etc/nginx/ssl/your_domain.pem;
ssl_certificate_key /etc/nginx/ssl/your_domain.key;
# SSL优化配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# 其余配置与HTTP版本相同
location /static/ {
alias /srv/django-app/static/;
}
location /media/ {
alias /srv/django-app/media/;
}
location / {
include uwsgi_params;
uwsgi_pass unix:/run/uwsgi/django.sock;
}
}
# HTTP自动跳转HTTPS
server {
listen 80;
server_name 你的域名;
return 301 https://$server_name$request_uri;
}配置完成后,重启Nginx使HTTPS生效。同时,在Django的`settings.py`中启用安全相关配置:
SECURE_SSL_REDIRECT = True SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True SECURE_HSTS_SECONDS = 31536000 SECURE_HSTS_INCLUDE_SUBDOMAINS = True
十、常见问题排查
10.1 502 Bad Gateway
这是Nginx无法连接uWSGI时最常见的错误。排查步骤:
确认uWSGI服务是否正在运行。
检查uWSGI的socket文件是否存在且权限正确。
检查Nginx配置中的`uwsgi_pass`路径是否与uWSGI配置文件中的`socket`路径一致。
查看uWSGI日志中的具体错误信息。
10.2 静态文件无法加载
如果页面可以访问但样式和图片丢失:
确认是否已执行`collectstatic`命令。
检查Nginx配置中`location /static/`的`alias`路径是否指向`STATIC_ROOT`目录。
检查静态文件目录的读取权限。
10.3 400 Bad Request
这通常是由于`ALLOWED_HOSTS`配置不当引起的。确保`ALLOWED_HOSTS`中包含了当前访问的域名或IP地址。当`DEBUG = False`时,Django对`ALLOWED_HOSTS`的校验非常严格。
10.4 no python application found
uWSGI启动时报“no python application found”错误。可能原因:
uWSGI配置中的`module`路径不正确。
虚拟环境未正确激活或`home`路径配置错误。
项目代码存在语法错误,导致应用无法加载。
10.5 Socket文件权限问题
Nginx无法访问uWSGI的socket文件时,会出现连接拒绝错误。确保`chmod-socket`设置为666或Nginx运行用户(通常为www-data或nginx)有读写权限。
10.6 修改代码后不生效
uWSGI默认不会自动重载代码。如需每次修改代码后自动生效,可在uWSGI配置中添加:
py-autoreload = 1
但生产环境不建议开启此功能,应通过重启uWSGI来加载新代码。
十一、性能优化建议
11.1 uWSGI参数调优
`workers`:通常设置为CPU核心数的2-4倍,可根据实际负载调整。
`threads`:每个工作进程的线程数,建议2-4之间。
`max-requests`:设置每个工作进程处理的最大请求数,达到后重启进程,有助于防止内存泄漏。
`buffer-size`:如果请求体较大(如文件上传),适当增大此值。
11.2 Nginx优化
启用Gzip压缩:在Nginx配置中添加`gzip on;`和相关指令,减少传输数据量。
配置静态文件缓存:通过`expires`指令设置缓存时间,减少重复请求。
调整`worker_processes`和`worker_connections`以匹配服务器资源。
11.3 数据库优化
生产环境务必使用MySQL、PostgreSQL等专业数据库,而非SQLite。
配置数据库连接池,减少连接开销。
为高频查询字段建立索引。
总结
本文系统介绍了在阿里云Linux云服务器上使用Nginx+uWSGI部署Django项目的完整流程。从架构原理、ECS实例创建、环境搭建、Django配置、uWSGI与Nginx的详细配置,到进程管理、域名SSL、问题排查和性能优化,涵盖了生产环境部署的各个环节。掌握这套部署方案后,开发者可以快速、稳定地将Django应用部署到云端,为用户提供高效可靠的Web服务。
Nginx和uWSGI的组合能够高效处理高并发请求,实现动静分离,是Django生产部署的成熟方案。希望本文能帮助读者顺利完成从开发到生产的跨越。
常见问题问答
问1:为什么要用Nginx+uWSGI部署Django,而不是直接用runserver?
答:Django自带的runserver是单进程开发服务器,不具备并发处理能力,且存在安全风险。Nginx+uWSGI组合能实现动静分离、负载均衡和高并发处理,是生产环境的标准部署方案。
问2:uWSGI使用Unix Socket和TCP端口通信有什么区别?
答:Unix Socket在同一台服务器上性能优于TCP端口,因为它避免了网络协议栈的开销。但如果Nginx和uWSGI部署在不同服务器上,则必须使用TCP端口通信。
问3:部署后访问页面出现502 Bad Gateway错误,如何解决?
答:502错误表示Nginx无法连接到uWSGI。首先检查uWSGI服务是否运行,然后确认socket文件路径在Nginx和uWSGI配置中一致,最后查看uWSGI日志获取详细错误信息。
问4:为什么修改了Django代码后页面没有变化?
答:uWSGI默认不会自动重载代码。修改代码后需要重启uWSGI服务才能生效。如需开发环境自动重载,可在uWSGI配置中添加`py-autoreload = 1`。
问5:静态文件(CSS/JS/图片)无法加载怎么办?
答:首先确认已执行`python manage.py collectstatic`收集静态文件。然后检查Nginx配置中`location /static/`的路径是否指向`STATIC_ROOT`目录。最后确认静态文件目录的读取权限是否正确。
问6:如何为Django项目配置HTTPS?
答:在阿里云申请免费SSL证书,将证书文件上传到服务器,修改Nginx配置文件添加443端口的server块,配置SSL证书路径,并设置HTTP自动跳转HTTPS。同时,在Django的settings.py中启用安全相关配置。



