当前位置:首页>php>PHP 容器的我!终于放弃了传统 Supervisord,转向当下最流行的 S6-overlay

PHP 容器的我!终于放弃了传统 Supervisord,转向当下最流行的 S6-overlay

  • 2026-10-21 13:28:21
PHP 容器的我!终于放弃了传统 Supervisord,转向当下最流行的 S6-overlay

概述

大家好,我是 Tinywan,一个在 Docker + PHP 生态里摸爬滚打好几年的老油条。

过去几年,我的 PHP 容器(Nginx + PHP-FPM + cron + 一些小脚本)几乎清一色用 supervisord 来管理多进程。配置简单,一个 ini 文件搞定所有服务,启动、重启、日志查看都挺顺手。很多老项目、公司内部镜像也都是这么玩的,稳定不出大问题,我就一直没换。

但从 2025 年下半年开始,我陆续迁移了几个核心服务到新镜像时,突然发现自己有点“跟不上时代”了。

为什么 supervisord 让我越来越不爽?

  1. 容器 stop 的时候关不干净docker stop 发 SIGTERM,supervisord 收到后会尝试优雅关闭子进程,但经常出现:主进程(supervisord 自己)不退出,导致容器卡在 “Stopping” 状态 10–30 秒,甚至要强制 kill -9。健康检查、滚动更新、蓝绿部署时特别烦。

  2. 僵尸进程(zombie)收割不彻底PHP 脚本偶尔 fork 出子进程(比如 exec() 调用 shell),supervisord 的 zombie reaping 能力一般,需要额外配置或 dumb-init 套娃。套娃多了,镜像就臃肿。

  3. 日志输出不 Docker friendly默认配置下,子进程的 stdout/stderr 会被 supervisord 接管并写文件,你得自己配置 [program:xxx] 的 stdout_logfile=syslog 或者重定向,才能让 docker logs 看到实时输出。配置一多就乱。

  4. Python 依赖 & 体积Alpine 基础镜像里塞个 Python(哪怕是 python3-minimal),体积增加 30–50MB 左右。启动也比纯 C 的东西慢一点点。

  5. 社区趋势已经变了linuxserver.io 全家桶、Home Assistant 插件、Nextcloud 官方 fpm 镜像、serversideup/php 系列、甚至 SeleniumHQ/docker-selenium 都在 2025 年陆续提迁移到 s6-overlay 的 issue。Reddit /r/docker 里搜 “supervisord vs s6”,新帖几乎全是推荐后者。

s6-overlay 到底好在哪里?

  • 天生为容器设计s6-overlay 的 /init 就是 PID 1,它会正确处理所有信号转发、zombie 回收、依赖启动顺序。docker stop 几乎秒退(通常 <2 秒)。

  • 日志直接 stdout服务 run 脚本里别重定向,全部输出就进 docker logs。debug 爽翻。

  • 极致轻量官方 noarch + arch 两个 tar.xz,加起来也就 3–5MB。纯 C + execline,无 Python 依赖。

  • 依赖关系写得优雅用 s6-rc 的 bundle + contents.d/ 目录结构定义依赖树。比如让 nginx 等 php-fpm ready 再启动,oneshot 初始化脚本(权限、目录、环境检查)也超级好写。

  • readiness 通知机制加个 notification-fd 文件(内容 3),s6 就知道你的服务真正 ready 了。比 supervisord 的简单 restart 策略靠谱多了。

迁移过程(以 PHP-Nginx 为例)

  1. 基础镜像从 php:8.3-fpm-alpine 改成 alpine:3.21 + 手动加 s6-overlay(固定版本 3.2.x)。
  2. 把 supervisord.conf 删掉,改成 s6-rc 目录结构:
/etc/s6-overlay/s6-rc.d/├── nginx/│   ├── run               # #!/usr/bin/execlineb -PW   with-contenv nginx -g "daemon off;"│   └── notification-fd   # 内容:3├── php-fpm/│   ├── run│   └── notification-fd├── init-permissions/     # oneshot 类型,启动前跑权限脚本│   ├── run│   └── type# 内容:oneshot└── user/                 # 默认 bundle    └── contents.d/        ├── php-fpm        └── nginx
  1. Dockerfile 里 COPY rootfs/ /  ,ENTRYPOINT ["/init"]

迁移后,镜像体积反而小了 20–40MB,docker stop 时间从 15s+ 降到 1–2s,docker logs 干净实时,健康检查也更准。

webman使用

拉取镜像

docker pull tinywan/docker-php-webman:8.4.16-s6

挂载启动webman

docker run --name webman-s6 --rm -it -p 8787:8787 -v /home/www/webman:/app tinywan/docker-php-webman:8.4.16-s6

输出日志

s6-rc: info: service s6rc-oneshot-runner: startings6-rc: info: service s6rc-oneshot-runner successfully starteds6-rc: info: service fix-attrs: startings6-rc: info: service fix-attrs successfully starteds6-rc: info: service legacy-cont-init: startings6-rc: info: service legacy-cont-init successfully starteds6-rc: info: service legacy-services: startings6-rc: info: service legacy-services successfully startedWorkerman[start.php] start in DEBUG modeMaster pid:67 is not alive-------------------------------------------- WORKERMAN ---------------------------------------------Workerman/5.1.6         PHP/8.4.16 (JIT off)          Linux/6.6.87.2-microsoft-standard-WSL2--------------------------------------------- WORKERS ----------------------------------------------event-loop  proto       user        worker      listen                 count       stateevent       tcp         root        webman      http://0.0.0.0:8787    16           [OK]event       tcp         root        monitor     none                   1            [OK]----------------------------------------------------------------------------------------------------Press Ctrl+C to stop. Start success.

查看进程

$ docker top webman-s6  acxfPID                 TTY                 STAT                TIME                COMMAND60483               ?                   Ss                  0:00                \_ s6-svscan60515               pts/0               Ss+                 0:00                \_ rc.init60566               pts/0               S+                  0:00                | \_ php60568               pts/0               S+                  0:00                | \_ php60569               pts/0               S+                  0:00                | \_ php60570               pts/0               S+                  0:00                | \_ php60571               pts/0               S+                  0:00                | \_ php60572               pts/0               S+                  0:00                | \_ php60573               pts/0               S+                  0:00                | \_ php60574               pts/0               S+                  0:00                | \_ php60575               pts/0               S+                  0:00                | \_ php60576               pts/0               S+                  0:00                | \_ php60577               pts/0               S+                  0:00                | \_ php60578               pts/0               S+                  0:00                | \_ php60579               pts/0               S+                  0:00                | \_ php60580               pts/0               S+                  0:00                | \_ php60581               pts/0               S+                  0:00                | \_ php60582               pts/0               S+                  0:00                | \_ php60583               pts/0               S+                  0:00                | \_ php60584               pts/0               S+                  0:00                | \_ php60516               ?                   S                   0:00                \_ s6-supervise60519               ?                   Ss                  0:00                | \_ s6-linux-init-s60526               ?                   S                   0:00                \_ s6-supervise60533               ?                   Ss                  0:00                | \_ s6-ipcserverd60527               ?                   S                   0:00                \_ s6-supervise

最后想说

supervisord 没有错,它在 2015–2024 年几乎是 Docker 多进程的事实标准。但到了 2025–2026 年,容器哲学更纯粹了:容器应该像单个进程一样行为。s6-overlay 更贴合这个理念,轻、准、现代。

如果你还在维护老项目,supervisord 继续用没问题。但新项目、特别是 PHP + Nginx/FPM + cron 的组合,我现在是 100% 推荐 s6-overlay。

你最近有没遇到 supervisord 的痛点?或者已经在用 s6 了?欢迎交流~

最新文章

随机文章