You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单容器部署Django+Gunicorn+Nginx:容器内Nginx重载问题咨询

解决Docker容器内Django+Gunicorn+Nginx的进程管理与Nginx重载问题

这个问题我之前帮朋友排查过,核心矛盾在于Docker的单进程运行模型——容器默认只会以你指定的CMD/ENTRYPOINT进程作为主进程,进程退出容器就会停止;再加上容器里没有完整的systemd环境,没法用systemctl管理服务。咱们一步步来搞定:

1. 为什么原来的方式行不通?

  • 你用CMD启动Gunicorn后,容器的主进程就是Gunicorn,此时手动启动Nginx只能让它在后台跑,容器的生命周期完全绑定Gunicorn,一旦Gunicorn退出容器就停。
  • 重启容器时,只会执行CMD定义的Gunicorn,Nginx不会自动启动;而且你没法在容器里用systemctl重载Nginx配置。

解决思路是用进程管理器同时管控Gunicorn和Nginx,让管理器作为容器的主进程,统一监控、启停两个服务。最常用的工具是supervisord。

2. 具体配置步骤

步骤1:在Dockerfile中安装supervisord

假设你用的是Debian/Ubuntu基础镜像,添加安装命令:

# 安装supervisord和依赖
RUN apt-get update && apt-get install -y supervisor nginx
# 创建supervisord日志目录
RUN mkdir -p /var/log/supervisor

步骤2:编写supervisord配置文件

在项目根目录创建supervisord.conf,内容如下:

[supervisord]
nodaemon=true  # 让supervisord前台运行,作为容器主进程

[program:gunicorn]
command=gunicorn --workers 3 --bind unix:/tmp/gunicorn.sock --umask 0007 your_project.wsgi:application
directory=/code  # 替换成你的Django项目根目录
user=www-data
autostart=true
autorestart=true
stdout_logfile=/var/log/supervisor/gunicorn.log
stderr_logfile=/var/log/supervisor/gunicorn.err.log

[program:nginx]
command=nginx -g "daemon off;"  # 关键:让Nginx前台运行,被supervisord监控
autostart=true
autorestart=true
stdout_logfile=/var/log/supervisor/nginx.log
stderr_logfile=/var/log/supervisor/nginx.err.log
  • --umask 0007是为了让Gunicorn生成的Unix Socket权限为rw-rw----,确保同组的Nginx进程能访问。
  • 替换your_project.wsgi:application为你实际的WSGI入口,/code为容器内的项目路径。

步骤3:修改Dockerfile,复制配置并设置启动命令

把supervisord配置和Nginx站点配置复制到容器里:

# 复制supervisord配置
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

# 复制Nginx站点配置(提前写好你的Nginx配置文件,比如nginx.conf)
COPY nginx.conf /etc/nginx/sites-available/django_project
RUN ln -s /etc/nginx/sites-available/django_project /etc/nginx/sites-enabled/
RUN rm /etc/nginx/sites-enabled/default  # 删除默认站点

# 设置容器启动命令为supervisord
CMD ["supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]

步骤4:确保Nginx配置指向Unix Socket

你的Nginx配置文件(nginx.conf)里要正确指向Gunicorn的Socket:

server {
    listen 80;
    server_name localhost;

    location / {
        proxy_pass http://unix:/tmp/gunicorn.sock;
        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;
    }
}

3. 如何重载Nginx配置?

容器运行后,你可以通过supervisorctl工具来管理Nginx,不用systemctl:

# 进入容器执行命令
docker exec -it your_container_name supervisorctl signal HUP nginx
# 或者直接重启Nginx进程
docker exec -it your_container_name supervisorctl restart nginx

HUP信号会让Nginx重新加载配置文件而不重启进程,比重启更轻量。

4. 常见坑点提醒

  • 一定要让Nginx前台运行(nginx -g "daemon off;"),否则supervisord会认为Nginx进程退出,不断尝试重启它。
  • Unix Socket的路径要完全一致:Gunicorn绑定的路径和Nginx配置里的proxy_pass路径必须相同。
  • 权限问题:确保Gunicorn和Nginx运行在同一用户/组(比如www-data),避免Socket访问被拒绝。

内容的提问来源于stack exchange,提问作者fogx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:55:22