supervisor 必须作为 pid 1 前台运行以管理多进程,docker 不支持多 cmd 或后台启动,否则容器会异常退出;需配置 nodaemon=true、各 program 段启用 autostart/autorestart,并用 supervisorctl 运维。

在 Docker 容器中用 Supervisor 管理多进程,核心是让 Supervisor 成为容器的主进程(PID 1),并正确配置它来启动和监控多个服务(如 Nginx + Gunicorn、Redis + Celery Worker 等)。Docker 原生只支持单个主进程,Supervisor 就是用来弥补这个限制的轻量级方案。
为什么不能直接用多个 CMD 或 & 启动?
Dockerfile 中的 CMD 只能指定一个主进程;用 & 后台启动多个命令会导致:容器因主进程退出而立即停止、无法接收信号(如 SIGTERM)、进程失去 PID 1 特权(无法转发信号、僵尸进程无法回收)。
正确做法:用 supervisord 作为 PID 1
Supervisor 必须以前台模式运行(-c /etc/supervisord.conf),且不能加 -d(守护模式),否则容器会启动后立刻退出。
- 在 Dockerfile 中安装 supervisor(如基于 Debian/Ubuntu:`apt-get install -y supervisor`)
- 准备自定义配置文件
/etc/supervisord.conf,启用[supervisord]段的nodaemon=true - 为每个要管理的进程写
[program:xxx]段,设置autostart=true、autorestart=true、startsecs=3等关键项 - CMD 改为:
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]
配置示例:同时跑 Nginx 和 Python Web 应用
假设项目结构含 app.py 和 /var/www/static,Nginx 配置已就绪:
-
[program:nginx]:command =/usr/sbin/nginx -g "daemon off;"(必须关守护模式) -
[program:web]:command =python3 /app/app.py,directory =/app,user =www-data - 加上
[supervisorctl]和[rpcinterface:supervisor](可选,用于 exec 进容器后调试) - 确保日志目录存在(如
/var/log/supervisor),并有写权限
调试与日常运维要点
容器启动后,可用 docker exec -it <container> supervisorctl status</container> 查看进程状态;supervisorctl restart web 可单独重启某服务。
- 所有子进程的标准输出/错误默认重定向到 supervisor 日志(可配
stdout_logfile分离) - 避免在 program 中使用 shell 特性(如
cd && python),改用directory+ 纯命令 - 若某进程启动慢或依赖其他服务,用
startretries和depends_on(需配合脚本判断依赖就绪) - 生产环境建议关闭
insecure_httpRPC 接口,或仅绑定本地地址










