引言

Nginx作为一款高性能的Web服务器和反向代理服务器,与Django这一强大的Python Web框架相结合,可以构建出高效、稳定的Web应用。本文将详细介绍如何使用nginx部署Django项目,从基础配置到高级优化,帮助您解决常见部署问题,提升网站性能与安全性,实现高效稳定运行。

环境准备

系统要求

在开始部署之前,确保您的系统满足以下基本要求:

  • 操作系统:Linux(推荐Ubuntu 20.04或CentOS 8)
  • Python:3.6或更高版本
  • Django:3.0或更高版本
  • Nginx:1.18或更高版本
  • 足够的内存和存储空间

安装必要的软件

安装Python和pip

在Ubuntu系统上,可以使用以下命令安装Python和pip:

sudo apt update sudo apt install python3 python3-pip python3-venv 

在CentOS系统上:

sudo yum update sudo yum install python3 python3-pip 

安装Django

创建一个虚拟环境并安装Django:

# 创建项目目录 mkdir myproject && cd myproject # 创建虚拟环境 python3 -m venv venv source venv/bin/activate # 安装Django pip install django 

安装Nginx

在Ubuntu系统上:

sudo apt install nginx 

在CentOS系统上:

sudo yum install epel-release sudo yum install nginx 

安装完成后,启动Nginx并设置开机自启:

sudo systemctl start nginx sudo systemctl enable nginx 

基础配置

创建Django项目

创建一个简单的Django项目用于演示:

# 创建Django项目 django-admin startproject myproject # 进入项目目录 cd myproject # 创建一个应用 python manage.py startapp myapp 

配置Django设置

编辑myproject/settings.py文件,进行基本配置:

import os # 基本设置 DEBUG = False # 生产环境应设置为False ALLOWED_HOSTS = ['your_domain.com', 'www.your_domain.com', 'localhost', '127.0.0.1'] # 应用定义 INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'myapp', # 添加我们的应用 ] # 中间件 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] # 根URL配置 ROOT_URLCONF = 'myproject.urls' # 模板设置 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] # WSGI应用 WSGI_APPLICATION = 'myproject.wsgi.application' # 数据库配置 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } # 密码验证 AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # 国际化 LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True # 静态文件设置 STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static'), ] # 默认主键字段类型 DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' 

配置Nginx

创建Nginx配置文件:

sudo nano /etc/nginx/sites-available/myproject 

添加以下配置:

server { listen 80; server_name your_domain.com www.your_domain.com; location = /favicon.ico { access_log off; log_not_found off; } location /static/ { root /path/to/your/project; } location /media/ { root /path/to/your/project; } location / { include proxy_params; proxy_pass http://unix:/run/gunicorn.sock; } } 

启用该配置:

sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled/ sudo nginx -t # 测试配置是否正确 sudo systemctl restart nginx 

WSGI服务器选择与配置

Gunicorn配置

Gunicorn是一个流行的WSGI HTTP服务器,用于运行Python Web应用程序。

安装Gunicorn:

pip install gunicorn 

创建Gunicorn服务文件:

sudo nano /etc/systemd/system/gunicorn.service 

添加以下内容:

[Unit] Description=gunicorn daemon After=network.target [Service] User=your_user Group=www-data WorkingDirectory=/path/to/your/project ExecStart=/path/to/your/project/venv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application [Install] WantedBy=multi-user.target 

创建Gunicorn socket文件:

sudo nano /etc/systemd/system/gunicorn.socket 

添加以下内容:

[Unit] Description=gunicorn socket [Socket] ListenRun=/run/gunicorn.sock [Install] WantedBy=sockets.target 

启动并启用Gunicorn服务:

sudo systemctl start gunicorn.socket sudo systemctl enable gunicorn.socket sudo systemctl status gunicorn.socket 

uWSGI配置

uWSGI是另一个流行的WSGI服务器,它提供了更多的配置选项和功能。

安装uWSGI:

pip install uwsgi 

创建uWSGI配置文件:

nano /path/to/your/project/myproject_uwsgi.ini 

添加以下内容:

[uwsgi] project = myproject base = /path/to/your/project chdir = %(base) home = %(base)/venv module = %(project).wsgi:application master = true processes = 5 socket = %(base)/%(project).sock chmod-socket = 664 vacuum = true die-on-term = true logto = /var/log/uwsgi/%(project).log 

创建日志目录:

sudo mkdir -p /var/log/uwsgi sudo chown -R your_user:www-data /var/log/uwsgi 

创建uWSGI服务文件:

sudo nano /etc/systemd/system/uwsgi.service 

添加以下内容:

[Unit] Description=uWSGI service for Django project After=network.target [Service] User=your_user Group=www-data WorkingDirectory=/path/to/your/project ExecStart=/path/to/your/project/venv/bin/uwsgi --ini myproject_uwsgi.ini [Install] WantedBy=multi-user.target 

启动并启用uWSGI服务:

sudo systemctl start uwsgi sudo systemctl enable uwsgi sudo systemctl status uwsgi 

高级优化

性能优化

Nginx性能优化

编辑Nginx主配置文件:

sudo nano /etc/nginx/nginx.conf 

在http块中添加或修改以下配置:

# worker进程数,通常设置为CPU核心数 worker_processes auto; # 每个worker进程的最大连接数 worker_connections 1024; # 启用gzip压缩 gzip on; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; # 客户端请求头缓冲区大小 client_header_buffer_size 1k; large_client_header_buffers 4 4k; # 客户端请求体大小限制 client_max_body_size 10M; # 启用文件缓存 open_file_cache max=1000 inactive=20s; open_file_cache_valid 30s; open_file_cache_min_uses 2; open_file_cache_errors on; # 超时设置 client_body_timeout 10; client_header_timeout 10; keepalive_timeout 5 5; send_timeout 10; 

Django性能优化

在Django的settings.py中添加以下配置:

# 缓存配置 CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.redis.RedisCache', 'LOCATION': 'redis://127.0.0.1:6379/1', } } # 会话配置 SESSION_ENGINE = "django.contrib.sessions.backends.cache" SESSION_CACHE_ALIAS = "default" # 数据库优化 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'mydatabase', 'USER': 'mydatabaseuser', 'PASSWORD': 'mypassword', 'HOST': 'localhost', 'PORT': '5432', 'CONN_MAX_AGE': 60, # 持久连接 } } # 模板优化 TEMPLATES[0]['OPTIONS']['loaders'] = [ ('django.template.loaders.cached.Loader', [ 'django.template.loaders.filesystem.Loader', 'django.template.loaders.app_directories.Loader', ]), ] # 静态文件优化 STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage' 

负载均衡

如果您的网站流量很大,可以使用Nginx的负载均衡功能来分配请求到多个应用服务器。

编辑Nginx配置文件:

sudo nano /etc/nginx/sites-available/myproject 

修改为以下配置:

upstream django_backend { server unix:/run/gunicorn1.sock; server unix:/run/gunicorn2.sock; server unix:/run/gunicorn3.sock; # 或者使用TCP/IP # server 127.0.0.1:8001; # server 127.0.0.1:8002; # server 127.0.0.1:8003; # 负载均衡方法 # least_conn; # 最少连接 # ip_hash; # 基于客户端IP的会话保持 } server { listen 80; server_name your_domain.com www.your_domain.com; location = /favicon.ico { access_log off; log_not_found off; } location /static/ { root /path/to/your/project; expires 30d; # 静态文件缓存30天 add_header Cache-Control "public, immutable"; } location /media/ { root /path/to/your/project; expires 30d; add_header Cache-Control "public, immutable"; } location / { include proxy_params; proxy_pass http://django_backend; # 健康检查 proxy_connect_timeout 5; proxy_read_timeout 30; } } 

缓存配置

Nginx缓存配置

在Nginx配置中添加缓存设置:

proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m inactive=60m use_temp_path=off; server { listen 80; server_name your_domain.com www.your_domain.com; location = /favicon.ico { access_log off; log_not_found off; } location /static/ { root /path/to/your/project; expires 30d; } location /media/ { root /path/to/your/project; expires 30d; } location / { proxy_cache my_cache; proxy_cache_valid 200 302 10m; proxy_cache_valid 404 1m; proxy_cache_key "$scheme$request_method$host$request_uri"; include proxy_params; proxy_pass http://unix:/run/gunicorn.sock; add_header X-Proxy-Cache $upstream_cache_status; } } 

Django缓存配置

在Django的settings.py中配置缓存:

# Redis缓存配置 CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379/1", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", } } } # 缓存页面 CACHE_MIDDLEWARE_ALIAS = 'default' CACHE_MIDDLEWARE_SECONDS = 600 # 缓存10分钟 CACHE_MIDDLEWARE_KEY_PREFIX = 'mysite_' # 会话缓存 SESSION_ENGINE = "django.contrib.sessions.backends.cache" SESSION_CACHE_ALIAS = "default" 

安全性配置

HTTPS配置

使用Let’s Encrypt免费SSL证书:

# 安装Certbot sudo apt install certbot python3-certbot-nginx # 获取SSL证书 sudo certbot --nginx -d your_domain.com -d www.your_domain.com # 自动续订证书 sudo crontab -e 

添加以下行以每天检查并续订证书:

0 12 * * * /usr/bin/certbot renew --quiet 

修改Nginx配置以支持HTTPS:

server { listen 80; server_name your_domain.com www.your_domain.com; return 301 https://$host$request_uri; } server { listen 443 ssl http2; server_name your_domain.com www.your_domain.com; ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384'; ssl_prefer_server_ciphers off; ssl_session_cache shared:SSL:10m; ssl_session_timeout 1d; ssl_session_tickets off; # HSTS add_header Strict-Transport-Security "max-age=63072000" always; location = /favicon.ico { access_log off; log_not_found off; } location /static/ { root /path/to/your/project; expires 30d; } location /media/ { root /path/to/your/project; expires 30d; } location / { include proxy_params; proxy_pass http://unix:/run/gunicorn.sock; } } 

安全头设置

在Nginx配置中添加安全头:

server { listen 443 ssl http2; server_name your_domain.com www.your_domain.com; # ... SSL配置 ... # 安全头 add_header X-Frame-Options "SAMEORIGIN" always; add_header X-XSS-Protection "1; mode=block" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "no-referrer-when-downgrade" always; add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always; # ... 其他配置 ... } 

Django安全设置

在Django的settings.py中添加安全配置:

# 安全设置 SECURE_SSL_REDIRECT = True SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True SECURE_BROWSER_XSS_FILTER = True SECURE_CONTENT_TYPE_NOSNIFF = True X_FRAME_OPTIONS = 'DENY' SECURE_HSTS_INCLUDE_SUBDOMAINS = True SECURE_HSTS_PRELOAD = True SECURE_HSTS_SECONDS = 31536000 # 1年 # 密码强度设置 AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 'OPTIONS': { 'min_length': 12, } }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # 登录安全 LOGIN_URL = '/accounts/login/' LOGIN_REDIRECT_URL = '/' LOGOUT_REDIRECT_URL = '/' 

常见问题与解决方案

502 Bad Gateway错误

问题:访问网站时出现502 Bad Gateway错误。

原因:通常是由于Nginx无法连接到后端应用服务器(如Gunicorn或uWSGI)。

解决方案

  1. 检查应用服务器是否正在运行:
sudo systemctl status gunicorn # 或 sudo systemctl status uwsgi 
  1. 如果服务未运行,启动它:
sudo systemctl start gunicorn # 或 sudo systemctl start uwsgi 
  1. 检查socket文件是否存在且权限正确:
ls -l /run/gunicorn.sock # 或 ls -l /path/to/your/project/myproject.sock 
  1. 检查Nginx错误日志:
sudo tail -f /var/log/nginx/error.log 
  1. 确保Nginx用户(通常是www-data)有权限访问socket文件:
sudo usermod -a -G www-data your_user 

静态文件404错误

问题:访问网站时静态文件(CSS、JavaScript、图片等)返回404错误。

原因:Nginx配置中的静态文件路径不正确,或者静态文件未收集到正确位置。

解决方案

  1. 收集静态文件:
cd /path/to/your/project source venv/bin/activate python manage.py collectstatic 
  1. 检查Nginx配置中的静态文件路径是否正确:
location /static/ { root /path/to/your/project; # 确保这是项目根目录 } 
  1. 确保Nginx有权限访问静态文件:
sudo chown -R www-data:www-data /path/to/your/project/staticfiles 
  1. 重新加载Nginx配置:
sudo systemctl reload nginx 

权限错误

问题:应用服务器无法访问项目文件或数据库。

原因:文件权限设置不正确。

解决方案

  1. 确保项目文件的所有权和权限正确:
sudo chown -R your_user:www-data /path/to/your/project sudo chmod -R 755 /path/to/your/project 
  1. 确保数据库文件权限正确(如果使用SQLite):
sudo chown www-data:www-data /path/to/your/project/db.sqlite3 sudo chmod 664 /path/to/your/project/db.sqlite3 
  1. 检查日志文件权限:
sudo touch /var/log/uwsgi/myproject.log sudo chown your_user:www-data /var/log/uwsgi/myproject.log sudo chmod 664 /var/log/uwsgi/myproject.log 

内存不足

问题:在高流量期间,服务器响应变慢或崩溃。

原因:服务器内存不足,无法处理所有请求。

解决方案

  1. 优化Gunicorn/uWSGI工作进程数:
# 对于Gunicorn worker_processes = (2 * CPU_CORES) + 1 # 对于uWSGI processes = 2 * CPU_CORES 
  1. 使用Nginx缓存减轻后端服务器负担:
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m inactive=60m use_temp_path=off; server { # ... 其他配置 ... location / { proxy_cache my_cache; proxy_cache_valid 200 302 10m; proxy_cache_valid 404 1m; # ... 其他配置 ... } } 
  1. 增加服务器内存或使用负载均衡:
upstream django_backend { server 10.0.0.1:8000; server 10.0.0.2:8000; server 10.0.0.3:8000; } 
  1. 优化Django查询,减少内存使用:
# 使用select_related或prefetch_related减少数据库查询 from django.db import models class Author(models.Model): name = models.CharField(max_length=100) class Book(models.Model): title = models.CharField(max_length=100) author = models.ForeignKey(Author, on_delete=models.CASCADE) # 不好的做法 books = Book.objects.all() for book in books: print(book.author.name) # 每次都会查询数据库 # 好的做法 books = Book.objects.select_related('author').all() for book in books: print(book.author.name) # 只查询一次数据库 

监控与日志

Nginx日志配置

配置Nginx访问日志和错误日志:

http { # 日志格式 log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; # 访问日志 access_log /var/log/nginx/access.log main; # 错误日志 error_log /var/log/nginx/error.log warn; # ... 其他配置 ... } server { # 访问日志 access_log /var/log/nginx/myproject_access.log main; # 错误日志 error_log /var/log/nginx/myproject_error.log warn; # ... 其他配置 ... } 

Django日志配置

在Django的settings.py中配置日志:

LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'verbose': { 'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}', 'style': '{', }, 'simple': { 'format': '{levelname} {message}', 'style': '{', }, }, 'handlers': { 'file': { 'level': 'INFO', 'class': 'logging.FileHandler', 'filename': '/var/log/django/myproject.log', 'formatter': 'verbose', }, 'console': { 'level': 'INFO', 'class': 'logging.StreamHandler', 'formatter': 'simple', }, }, 'loggers': { 'django': { 'handlers': ['file', 'console'], 'level': 'INFO', 'propagate': True, }, 'myapp': { 'handlers': ['file', 'console'], 'level': 'DEBUG', 'propagate': False, }, }, } 

创建日志目录并设置权限:

sudo mkdir -p /var/log/django sudo chown -R www-data:www-data /var/log/django 

监控工具

使用Prometheus和Grafana监控

安装Prometheus和Grafana:

# 安装Prometheus sudo apt install prometheus # 安装Grafana sudo apt install grafana 

配置Prometheus监控Nginx和Django:

# /etc/prometheus/prometheus.yml global: scrape_interval: 15s scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['localhost:9090'] - job_name: 'nginx' static_configs: - targets: ['localhost:9113'] - job_name: 'django' static_configs: - targets: ['localhost:8000'] 

安装Nginx exporter:

# 安装nginx-prometheus-exporter sudo apt install nginx-prometheus-exporter 

配置Django监控:

# 安装django-prometheus pip install django-prometheus # 在settings.py中添加 INSTALLED_APPS = [ # ... 'django_prometheus', # ... ] MIDDLEWARE = [ 'django_prometheus.middleware.PrometheusBeforeMiddleware', # ... 'django_prometheus.middleware.PrometheusAfterMiddleware', ] 

使用Sentry进行错误跟踪

安装Sentry SDK:

pip install sentry-sdk 

在Django的settings.py中配置Sentry:

import sentry_sdk from sentry_sdk.integrations.django import DjangoIntegration sentry_sdk.init( dsn="YOUR_SENTRY_DSN", integrations=[DjangoIntegration()], traces_sample_rate=1.0, send_default_pii=True ) 

总结

通过本文的详细介绍,您应该已经掌握了使用nginx部署Django项目的关键技术,从基础配置到高级优化。以下是一些关键要点:

  1. 环境准备:确保系统满足基本要求,正确安装Python、Django和Nginx。

  2. 基础配置:合理配置Django设置文件和Nginx配置文件,确保静态文件和媒体文件正确处理。

  3. WSGI服务器:选择适合的WSGI服务器(如Gunicorn或uWSGI)并正确配置。

  4. 性能优化:通过Nginx和Django的各种优化策略,如缓存、压缩、负载均衡等,提升网站性能。

  5. 安全性配置:启用HTTPS,设置安全头,加强Django安全设置,保护网站免受攻击。

  6. 问题解决:了解常见部署问题及其解决方案,快速定位并解决问题。

  7. 监控与日志:配置适当的日志和监控系统,及时发现问题并优化性能。

通过遵循本文提供的指南,您可以构建一个高效、稳定、安全的Django网站,为用户提供优质的访问体验。记住,部署是一个持续优化的过程,随着业务的发展和技术的进步,您需要不断调整和优化您的部署策略,以适应不断变化的需求。