Django 多域名部署下 Nginx location 配置规则怎么写?

文章导读
在 Django 多域名部署场景中,核心在于利用 Nginx 的 server 块区分域名,而非 location 规则。每个域名对应一个 server 配置,通过 proxy_pass 统一转发至 Django 后端,并配合 Django 的 ALLOWED_HOSTS 进行安全校验。
📋 目录
  1. 核心概念澄清
  2. 生产环境 Nginx 配置示例
  3. Django 设置配合
  4. 验证方法
  5. 常见坑
A A

Django 多域名部署下 Nginx server 块配置指南

在 Django 多域名部署场景中,核心在于利用 Nginx 的 server 块区分域名,而非 location 规则。每个域名对应一个 server 配置,通过 proxy_pass 统一转发至 Django 后端,并配合 Django 的 ALLOWED_HOSTS 进行安全校验。

先说结论:多域名指向同一 Django 项目时,Nginx 侧按域名分流,Django 侧统一接收,重点在于 Host 头传递和安全校验。

  • 适合单 Django 实例响应多个域名或子域名的场景
  • 区分域名依赖 server_name 而非 location
  • 生产环境需配置 HTTPS 及 Gunicorn/uWSGI 上游地址
  • 验收时检查 Django 日志是否收到正确的 Host 头

核心概念澄清

Nginx 处理请求时,先根据 listen 端口和 server_name 匹配到对应的 server 块,再根据 location 规则处理请求路径。多域名分流的关键在于 server_name 配置,而不是 location

对于 Django 项目,通常需要将请求反向代理给 Gunicorn 或 uWSGI。Django 自身会通过 ALLOWED_HOSTS 校验请求头中的 Host 字段。如果 Nginx 透传的 Host 不在允许列表中,Django 会直接返回 400 错误。因此,配置的核心在于 Nginx 正确传递 Host 头,且 Django 放行该域名。

生产环境 Nginx 配置示例

以下配置包含 upstream 定义、HTTP 强制跳转 HTTPS 以及 HTTPS 服务块,适用于生产环境。

# 定义后端上游服务,避免硬编码端口
upstream django_backend {
    server 127.0.0.1:8000; 
    # 生产环境建议指向 Gunicorn/uWSGI socket 或端口
    # 例如:server unix:/run/gunicorn.sock;
}

# HTTP 强制跳转 HTTPS
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

# HTTPS 配置
server {
    listen 443 ssl;
    server_name example.com www.example.com;

    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;

    location / {
        proxy_pass http://django_backend;
        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;
    }

    # 静态文件由 Nginx 直接处理
    location /static/ {
        alias /var/www/example.com/static/;
    }
}

如果有多个域名,复制 server 块并修改 server_name 和 SSL 证书路径即可,proxy_pass 指向同一个 upstream 地址。

Django 设置配合

1. 配置 ALLOWED_HOSTS

Django 多域名部署下 Nginx location 配置规则怎么写?

settings.py 中找到 ALLOWED_HOSTS,将所有需要响应的域名加入列表。例如:

ALLOWED_HOSTS = ['example.com', 'www.example.com', 'blog.example.com']

2. 处理 HTTPS 代理头

如果 Nginx 开启了 HTTPS 且后端是 HTTP,建议在 settings.py 中设置以下参数,以便 Django 识别正确的协议和 Host:

USE_X_FORWARDED_HOST = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

3. 收集静态文件

确保 Django 运行过 python manage.py collectstatic 命令,且 Nginx 配置中的 alias 路径与 STATIC_ROOT 一致。

验证方法

1. 使用 curl 测试

在服务器本地执行 curl 命令,模拟不同域名请求,检查状态码和 Header:

Django 多域名部署下 Nginx location 配置规则怎么写?
# 测试 HTTP 跳转
curl -I http://example.com

# 测试 HTTPS 及 Host 头
curl -I -H "Host: example.com" https://127.0.0.1

观察返回状态码是否为 200 或 301,而不是 400 或 502。

2. 检查日志

查看 Nginx 的 access.log 确认请求是否命中对应的 server_name。查看 Django 应用日志,确认没有抛出 DisallowedHost 异常。

常见坑

1. ALLOWED_HOSTS 漏写

这是最常见的问题。每增加一个新域名,必须同步更新 Django 配置并重启服务,否则该域名访问会报 400 Bad Request。

Django 多域名部署下 Nginx location 配置规则怎么写?

2. HTTPS 重定向循环

如果 Nginx 处理 SSL 终结,而 Django 也强制 HTTPS,可能产生重定向循环。需在 Django 中配置 SECURE_SSL_REDIRECT = False,依赖 Nginx 做跳转,或者正确传递 X-Forwarded-Proto 头。

3. 后端地址配置错误

开发环境常用 runserver 监听 8000 端口,但生产环境应使用 Gunicorn 或 uWSGI。直接复制 8000 端口配置到生产环境可能导致连接失败或性能问题。

4. 静态文件路径混淆

多域名共用静态文件时,确保 Nginx 的 rootalias 路径指向正确,避免因为域名不同导致静态资源 404。