阿里云ECS云服务器部署Django网站:uWSGI+Nginx全套配置代码与实战指南
一、为什么选择Nginx+uWSGI部署Django
Django框架自带的开发服务器(runserver)虽然方便调试,但性能低下、不具备并发处理能力,绝不能用于生产环境。生产环境部署Django项目,业界公认的最佳实践是采用Nginx作为前端反向代理服务器,配合uWSGI作为应用服务器,共同构建一个高性能、高可用的Web服务架构。
这套架构的核心优势体现在以下几个方面。Nginx具备极强的静态资源处理能力,当浏览器发起请求时,Nginx作为前端服务器率先接收请求。如果请求的是CSS、JavaScript、图片等静态文件,Nginx直接从服务器本地文件系统读取并返回,完全不需要经过Django应用。这种动静分离的设计大幅减轻了Django应用的负载,让Python进程专注于处理动态业务逻辑。uWSGI是一个全功能的WSGI应用服务器,专门负责运行Python Web应用。它通过WSGI协议与Django应用通信,将Nginx转发过来的动态请求传递给Django处理,再将Django的响应打包返回给Nginx。uWSGI支持多进程、多线程、异步等多种并发模型,可以根据服务器配置灵活调整。
这套架构的工作流程可以概括为:用户浏览器发送HTTP请求到达服务器,Nginx接收请求后判断类型,静态文件直接由Nginx返回,动态请求通过uwsgi协议转发给uWSGI,uWSGI通过WSGI接口调用Django应用处理业务逻辑,Django处理完成后将响应逐层返回给用户。Nginx与uWSGI之间采用uwsgi协议进行通信,这是一种比HTTP更高效的二进制协议,专门为Nginx与uWSGI的协作而设计。
需要先登录阿里云控制台,点击:阿里云控制台
二、ECS实例准备与安全组配置
2.1 选购ECS实例
登录阿里云控制台后,进入ECS云服务器产品页面购买实例。对于初次部署Django项目的开发者,推荐以下配置。地域选择上,国内项目建议优先考虑华东1(杭州)或华北2(北京),选择离目标用户群最近的地域可以有效降低网络延迟。实例规格方面,入门级项目至少选择2核4GB内存的配置,能够满足大多数中小型Python Web应用的运行需求;如果预算有限且项目规模较小,1核2GB也可以起步,但后续扩展空间有限。操作系统推荐Ubuntu 22.04 LTS或Alibaba Cloud Linux 3,前者社区活跃、资料丰富,后者是阿里云官方优化的系统,性能和兼容性更佳。系统盘建议至少40GB高效云盘或SSD云盘,带宽初期选择1-3Mbps按量计费即可,后续可根据实际访问量调整。
2.2 安全组规则配置
安全组是阿里云最重要的网络访问控制机制,相当于云服务器的防火墙。创建ECS实例后,必须正确配置安全组的入方向规则,否则外部网络无法访问你的服务。需要开放以下关键端口。22端口用于SSH远程登录,来源IP建议设置为你的本地IP或公司IP段,避免暴露给全网带来安全风险。80端口是HTTP网站访问端口,来源设置为0.0.0.0/0,允许所有用户访问。443端口用于HTTPS加密访问,后续配置SSL证书后会使用到。8001端口用于测试uWSGI服务是否正常运行,8002端口用于测试Django项目是否部署成功,这两个端口在调试阶段使用,生产环境可以关闭或通过Nginx代理。
安全组配置应遵循最小权限原则,只开放业务必需的端口和IP段。创建实例时如果选择「新建安全组」并勾选HTTP(TCP:80),系统会自动放行80端口。建议定期审计安全组规则,及时删除过期或冗余的规则。
三、服务器环境初始化
3.1 SSH远程连接
获取ECS实例的公网IP地址后,使用SSH命令连接服务器。
ssh root@你的ECS公网IP首次登录会提示确认安全指纹或修改密码。出于安全考虑,建议创建一个非root用户用于日常操作。
adduser deploy
usermod -aG sudo deploy3.2 更新系统与安装基础工具
登录后首先更新系统包索引,并安装基础开发工具。
sudo apt update
sudo apt upgrade -y
sudo apt install -y python3 python3-pip python3-venv python3-dev
gcc make pcre-devel zlib-devel git curl wget对于Alibaba Cloud Linux或CentOS系统,使用yum包管理器。
sudo yum update -y
sudo yum install -y python3.8 python38-devel pcre-devel gcc make git curl wget3.3 安装Nginx
默认源的Nginx版本通常较旧,可能存在安全风险。建议添加Nginx官方源以安装最新的稳定版本。
sudo tee /etc/yum.repos.d/nginx.repo <<-'EOF'
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/8/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
EOF
sudo yum install -y nginxUbuntu系统则直接使用apt安装即可。
sudo apt install -y nginx安装完成后启动Nginx并设置开机自启。
sudo systemctl start nginx
sudo systemctl enable nginx四、部署Django项目
4.1 创建项目目录与虚拟环境
在服务器上创建统一的项目目录,用于存放Django代码、日志、静态文件和媒体文件。
sudo mkdir -p /srv/django-app/{logs,static,media}
sudo mkdir -p /run/uwsgi
sudo chown -R $USER:$USER /srv/django-app
sudo chown -R $USER:$USER /run/uwsgi创建Python虚拟环境以隔离项目依赖,避免不同项目间的包版本冲突。
cd /srv/django-app
python3 -m venv venv
source venv/bin/activate4.2 上传项目代码与安装依赖
将本地开发完成的Django项目代码上传至服务器。可以通过Git克隆、scp命令或FTP工具等方式。假设项目代码放在 /srv/django-app 目录下。
git clone 你的项目仓库地址 .
# 或者使用scp从本地上传
# scp -r ./myproject root@你的ECS公网IP:/srv/django-app/在虚拟环境中安装项目依赖。
pip install --upgrade pip wheel -i https://mirrors.aliyun.com/pypi/simple
pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple
pip install uwsgi -i https://mirrors.aliyun.com/pypi/simple4.3 配置Django生产环境settings
修改项目配置文件 /srv/django-app/myproject/settings.py,以满足生产环境的安全和性能要求。
# 关闭调试模式,防止应用出错时泄露敏感信息
DEBUG = False
# 设置允许访问的主机,必须包含服务器的公网IP或域名
ALLOWED_HOSTS = ['你的ECS公网IP', '你的域名.com']
# 配置静态文件收集目录
STATIC_ROOT = BASE_DIR / 'static'
# 配置媒体文件目录
MEDIA_ROOT = BASE_DIR / 'media'
MEDIA_URL = '/media/'如果使用MySQL或PostgreSQL等生产级数据库,需要修改DATABASES配置。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'your_database',
'USER': 'your_user',
'PASSWORD': 'your_password',
'HOST': 'localhost',
'PORT': '3306',
}
}4.4 收集静态文件与数据库迁移
执行collectstatic命令,将项目中的所有静态文件集中到STATIC_ROOT指定的目录,供Nginx直接提供服务。
python /srv/django-app/manage.py collectstatic --noinput执行数据库迁移,在数据库中创建应用所需的表结构。
python /srv/django-app/manage.py migrate创建超级用户以便管理后台。
python /srv/django-app/manage.py createsuperuser五、uWSGI配置详解
5.1 创建uWSGI配置文件
在Django项目根目录下创建uWSGI配置文件,通常命名为 uwsgi.ini。
sudo vim /srv/django-app/uwsgi.ini以下是完整的uWSGI配置文件内容,每一行都有详细注释说明其作用。
[uwsgi]
# 项目根目录的绝对路径
chdir = /srv/django-app
# Django项目的WSGI模块路径(指向项目同名目录下的wsgi.py)
module = myproject.wsgi:application
# 使用Unix socket文件与Nginx通信(比TCP端口更高效、更安全)
socket = /run/uwsgi/django.sock
# socket文件的权限,确保Nginx用户可读写
chmod-socket = 666
# 清理socket文件(停止uWSGI时自动删除)
vacuum = true
# 主进程模式
master = true
# 进程数,建议设置为CPU核心数乘以2
processes = 4
# 每个进程的线程数
threads = 2
# 每个进程处理请求的最大数量,防止内存泄漏
max-requests = 5000
# 以守护进程方式运行,指定日志文件
daemonize = /srv/django-app/logs/uwsgi.log
# 日志文件权限
log-rotation = true
# 设置环境变量,指定Django的配置文件
env = DJANGO_SETTINGS_MODULE=myproject.settings
# 指定Python虚拟环境路径
home = /srv/django-app/venv
# 设置进程运行的uid和gid(使用非特权用户更安全)
uid = deploy
gid = deploy
# 启用线程支持
enable-threads = true
# 进程启动后延迟加载应用
lazy-apps = true5.2 uWSGI配置参数详解
chdir参数指定Django项目的根目录,uWSGI启动时会切换到这个目录下工作。module参数指定WSGI应用的入口,myproject.wsgi:application表示从myproject/wsgi.py文件中导入application对象。socket参数指定与Nginx通信的Unix socket文件路径,使用socket方式比HTTP方式性能更好、安全性更高。chmod-socket=666确保Nginx进程有权限读写该socket文件。master=true启用主进程模式,主进程负责管理子进程,当子进程异常退出时主进程会自动重启。processes参数设置工作进程数量,一般建议设置为CPU核心数的2倍。threads参数设置每个工作进程的线程数,可根据应用类型调整。max-requests参数设置每个进程处理多少请求后自动重启,可以有效防止内存泄漏问题。daemonize参数将uWSGI转为后台守护进程运行,并将日志输出到指定文件。home参数指向Python虚拟环境的路径,确保uWSGI使用正确的Python解释器和依赖包。uid和gid参数指定运行进程的用户和用户组,使用非特权用户运行服务可以提升安全性,即使应用被攻破,攻击者也无法获得服务器的最高权限。
5.3 测试uWSGI是否正常运行
先用命令行方式启动uWSGI测试配置是否正确。
cd /srv/django-app
source venv/bin/activate
uwsgi --ini uwsgi.ini查看日志文件确认启动成功。
tail -f /srv/django-app/logs/uwsgi.log如果看到类似 "uWSGI running" 的提示,说明uWSGI已成功启动并监听socket文件。
六、Nginx配置详解
6.1 创建Nginx站点配置文件
Nginx的站点配置文件通常放在 /etc/nginx/conf.d/ 或 /etc/nginx/sites-available/ 目录下。创建一个名为 django.conf 的配置文件。
sudo vim /etc/nginx/conf.d/django.conf以下是完整的Nginx配置文件内容。
upstream django {
# 与uWSGI的socket配置保持一致
server unix:/run/uwsgi/django.sock fail_timeout=0;
}
server {
# 监听80端口
listen 80;
# 服务器域名或IP
server_name 你的ECS公网IP 你的域名.com;
# 字符集设置
charset utf-8;
# 客户端上传文件大小限制
client_max_body_size 100M;
# 日志配置
access_log /srv/django-app/logs/nginx_access.log;
error_log /srv/django-app/logs/nginx_error.log;
# 静态文件处理 - 由Nginx直接提供
location /static/ {
alias /srv/django-app/static/;
expires 30d;
}
# 媒体文件处理 - 由Nginx直接提供
location /media/ {
alias /srv/django-app/media/;
expires 30d;
}
# 动态请求转发给uWSGI
location / {
include /etc/nginx/uwsgi_params;
uwsgi_pass django;
uwsgi_read_timeout 60s;
uwsgi_connect_timeout 60s;
uwsgi_send_timeout 60s;
}
# 健康检查路径(可选)
location /health/ {
include /etc/nginx/uwsgi_params;
uwsgi_pass django;
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
}
}6.2 Nginx配置参数详解
upstream django 定义了一个上游服务器组,指向uWSGI监听的Unix socket文件。server_name 指定该站点配置对应的域名或IP,可以同时配置多个。location /static/ 和 location /media/ 两个配置块负责处理静态文件和媒体文件的请求。alias指令指定文件在服务器上的实际存放路径,expires 30d 设置浏览器缓存时间为30天,大幅提升静态资源的加载速度。location / 配置块处理所有其他请求,通过 uwsgi_pass 指令将请求转发给uWSGI服务器。include /etc/nginx/uwsgi_params 导入uWSGI标准参数文件,该文件包含了uWSGI协议所需的必要参数。uwsgi_read_timeout、uwsgi_connect_timeout、uwsgi_send_timeout 分别设置读取、连接、发送的超时时间,防止长时间请求阻塞。location ~ /\. 配置用于禁止用户访问以点开头的隐藏文件(如 .env、.git 等),提升安全性。
6.3 测试并重启Nginx
配置完成后,先测试Nginx配置文件语法是否正确。
sudo nginx -t如果输出 "syntax is ok" 和 "test is successful",说明配置无误。然后重启Nginx使配置生效。
sudo systemctl restart nginx检查Nginx运行状态。
sudo systemctl status nginx七、进程管理与开机自启
7.1 使用Supervisor管理uWSGI进程
在生产环境中,uWSGI进程可能因各种原因意外退出,需要有一个进程守护工具来自动重启服务。Supervisor是Python生态中最常用的进程管理工具,它不仅能自动重启崩溃的服务,还提供统一的日志收集、进程分组管理、细粒度权限控制等企业级功能。
安装Supervisor。
sudo apt install -y supervisor
# CentOS/Alibaba Cloud Linux
sudo yum install -y supervisor创建Supervisor配置文件 /etc/supervisor/conf.d/django.conf。
sudo vim /etc/supervisor/conf.d/django.conf配置文件内容如下。
[program:django]
# 启动命令
command=/srv/django-app/venv/bin/uwsgi --ini /srv/django-app/uwsgi.ini
# 工作目录
directory=/srv/django-app
# 运行用户
user=deploy
# 自动启动
autostart=true
# 自动重启
autorestart=true
# 重启等待时间(秒)
startsecs=5
# 停止信号
stopsignal=INT
# 停止等待时间(秒)
stopwaitsecs=60
# 日志文件
stdout_logfile=/srv/django-app/logs/supervisor_stdout.log
stderr_logfile=/srv/django-app/logs/supervisor_stderr.log
# 环境变量
environment=DJANGO_SETTINGS_MODULE="myproject.settings"重新加载Supervisor配置并启动服务。
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start django查看进程状态。
sudo supervisorctl status7.2 设置Supervisor开机自启
确保Supervisor服务本身开机自启。
sudo systemctl enable supervisor
sudo systemctl start supervisor这样,服务器重启后Supervisor会自动启动,并自动拉起uWSGI进程,无需人工干预。
八、常见问题排查
8.1 502 Bad Gateway错误
502错误是最常见的部署问题,通常意味着Nginx无法与uWSGI建立有效通信。排查步骤依次检查以下几点。确认uWSGI进程是否正在运行,使用 ps aux | grep uwsgi 或 supervisorctl status 查看进程状态。检查uWSGI的socket文件是否存在以及权限是否正确,ls -la /run/uwsgi/django.sock 查看文件权限,确保Nginx用户(通常是www-data或nginx)有读写权限。检查Nginx配置文件中的 uwsgi_pass 路径是否与uWSGI配置文件中的 socket 路径完全一致。查看uWSGI日志 /srv/django-app/logs/uwsgi.log 和Nginx错误日志 /srv/django-app/logs/nginx_error.log,寻找具体的错误信息。
8.2 静态文件404错误
静态文件无法加载通常是因为Nginx没有正确配置静态文件路径。首先确认是否执行了 collectstatic 命令,静态文件是否已收集到 STATIC_ROOT 指定的目录。检查Nginx配置中 location /static/ 的 alias 路径是否与 STATIC_ROOT 一致。检查目录权限,确保Nginx用户有读取静态文件目录的权限。如果使用了自定义的静态文件目录,确保在Nginx配置中正确添加了对应的 location 配置。
8.3 ALLOWED_HOSTS配置错误
当DEBUG=False时,如果ALLOWED_HOSTS配置不正确,Django会返回HTTP 400错误。确保 ALLOWED_HOSTS 列表中包含了访问网站时使用的域名或IP地址。如果通过IP访问,需要将IP地址作为字符串加入列表;如果通过域名访问,需要将域名加入列表。
8.4 数据库连接问题
如果使用MySQL或PostgreSQL等外部数据库,常见问题包括数据库服务未启动、数据库配置信息错误、网络不通等。确认数据库服务正在运行,检查settings.py中的数据库连接信息(HOST、PORT、USER、PASSWORD、NAME)是否正确,检查数据库用户是否有足够的权限访问对应的数据库。
8.5 端口被占用或防火墙问题
如果服务无法启动,可能是端口被占用。使用 netstat -tlnp 或 ss -tlnp 查看端口占用情况。确认安全组规则已正确放行所需端口。检查服务器本机的防火墙(如ufw或firewalld)是否放行了相应端口。
九、性能优化建议
uWSGI的processes参数应根据服务器的CPU核心数进行调整,一般建议设置为CPU核心数的2倍。threads参数可根据应用类型调整,IO密集型应用可以适当增加线程数。Nginx的静态文件缓存时间可以适当延长,减少重复请求对服务器的压力。启用Nginx的gzip压缩功能,减少传输数据量。使用CDN加速静态资源的全球分发。定期清理日志文件,避免日志占用过多磁盘空间。
十、总结
在阿里云ECS云服务器上使用Nginx+uWSGI部署Django项目,是一套经过大规模生产环境验证的成熟方案。这套架构通过Nginx处理静态资源、uWSGI运行动态应用、动静分离的设计理念,能够充分发挥服务器的性能,应对高并发访问场景。部署过程中需要关注几个核心环节:安全组端口放行、Django生产环境配置、uWSGI与Nginx配置的路径一致性、进程守护与开机自启。本文提供的配置文件模板和命令脚本均可在实际项目中直接使用,开发者只需根据实际项目路径和域名进行相应调整即可。从开发到上线,掌握这套部署流程是每一个Django开发者必备的技能。



