同一域名下Gunicorn+Nginx部署多Django应用故障排查
多Django应用路径式部署问题排查与解决方案
问题背景
现有静态网站domain.com,已部署可正常运行的Django应用djangoapp1(访问路径domain.com/djangoapp1),拟新增Django应用djangoapp2(访问路径domain.com/djangoapp2)。当前Nginx的sites-available配置已链接至sites-enabled,djangoapp1运行正常,但djangoapp2仅能通过手动执行gunicorn --bind 127.0.0.1:7000 config.wsgi启动,通过systemd服务启动失败(状态显示exit-code 1),且djangoapp2.sock文件存在。需求为不使用子域名,以路径形式部署多应用。
附用户提供的Nginx配置
server { listen 80; listen [::]:80; server_name domain.com www.domain.com; return 301 https://$host$request_uri; } #upstream djangoapp1 { # This did not work # server 127.0.0.1:9000 fail_timeout=0; #} #upstream djangoapp2 { # This did not work # server 127.0.0.1:7000 fail_timeout=0; #} server { listen 443 ssl; server_name ...; ssl_certificate ... ssl_certificate_key ...; root /var/www/portfolio; #Serves static portfolio and works index index.html; #Serves static portfolio and works location / { try_files $uri $uri/ =404; } location /djangoapp1static/ { #Works for app 1 and matches settings alias /home/djangoapp1... } location /djangoapp2static/ { alias /home/djangoapp2... } location /djangoapp1{ alias /home/djangoapp1/src/; include proxy_params; proxy_pass http://unix:/run/gunicorn.sock; #WORKS #proxy_pass http://djangoapp1; #Does not work even without the second app #proxy_pass http://127.0.0.1:9000; #Does not work even without the second app } location /djangoapp2{ alias /home/djangoapp2/src/; include proxy_params; proxy_pass http://unix:/run/djangoapp2.sock; #This works for djangoapp1 but not for this one #proxy_pass http://djangoapp2; #Tried did not work #proxy_pass http://127.0.0.1:7000; #Tried did not work } }
附systemd状态信息
× djangoapp2.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/djangoapp2.service; enabled; preset: enabled) Active: failed (Result: exit-code) since Fri 2022-12-23 08:04:16 UTC; 41min ago Duration: 462ms TriggeredBy: × djangoapp2.socket Main PID: 47712 (code=exited, status=1/FAILURE) CPU: 455ms
解决方案
一、修复systemd服务启动失败问题
手动启动gunicorn正常但systemd失败,核心原因大概率是服务配置错误或权限问题:
- 查看详细错误日志
执行以下命令获取启动失败的具体原因:
journalctl -u djangoapp2.service -e
日志会明确指出错误,比如虚拟环境路径错误、工作目录不存在、权限不足等。
- 检查并修正systemd服务文件
确保/etc/systemd/system/djangoapp2.service配置正确,示例如下:
[Unit] Description=gunicorn daemon for djangoapp2 After=network.target [Service] User=www-data Group=www-data WorkingDirectory=/home/djangoapp2/src # 必须指向djangoapp2的项目根目录 ExecStart=/home/djangoapp2/venv/bin/gunicorn --workers 3 --bind unix:/run/djangoapp2.sock --umask 007 config.wsgi:application # 注意:ExecStart中的gunicorn路径必须是djangoapp2虚拟环境内的可执行文件,不能用全局gunicorn [Install] WantedBy=multi-user.target
--umask 007确保生成的sock文件权限为rw-rw----,让Nginx能正常访问。- 若使用socket激活(TriggeredBy显示djangoapp2.socket),需确保socket文件配置的路径与service一致。
- 修复权限问题
执行以下命令确保相关目录和文件权限正确:
chown -R www-data:www-data /home/djangoapp2/src chmod -R 755 /home/djangoapp2/src
若sock文件已存在,手动修正权限:
chown www-data:www-data /run/djangoapp2.sock
- 重启服务验证
systemctl daemon-reload systemctl start djangoapp2.service systemctl status djangoapp2.service
确认服务状态变为active (running)即可。
二、调整Nginx配置确保路径转发正确
原配置中location /djangoapp2使用alias会导致请求路径映射混乱,需调整为适配Django路径前缀的配置:
- 修正djangoapp2的location块
替换原有的location /djangoapp2配置为:
location /djangoapp2 { include proxy_params; proxy_pass http://unix:/run/djangoapp2.sock; proxy_set_header SCRIPT_NAME /djangoapp2; # 告诉Django应用的路径前缀 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; }
- 移除
alias配置,避免路径映射错误。 proxy_set_header SCRIPT_NAME是关键,让Django知道自己的访问前缀是/djangoapp2。
- 配置djangoapp2的settings.py
在djangoapp2的settings.py中添加以下配置:
FORCE_SCRIPT_NAME = '/djangoapp2' STATIC_URL = '/djangoapp2static/' # 若有媒体文件,同样设置MEDIA_URL前缀 MEDIA_URL = '/djangoapp2media/'
执行静态文件收集:
python manage.py collectstatic
- 重启Nginx
systemctl reload nginx
三、测试验证
访问domain.com/djangoapp2,确认应用正常加载;访问domain.com/djangoapp2static/验证静态文件可正常访问。
内容的提问来源于stack exchange,提问作者Vinko Oakniiv
相关产品推荐
相关产品推荐

