现 LinuxServer.io 那种 PUID/PGID

最后发布时间 : 2026-08-18 10:48:30 浏览量 :

这个脚本是 s6-overlay 3.x 的容器入口初始化脚本。它本身不负责修改 PUID/PGID,主要负责:

  1. 确保 /bin/usr/bin/commandPATH
  2. 等待 Docker readiness fd
  3. 调用 s6-overlay-suexec
  4. 以 root 执行 preinit
  5. 然后进入 stage0
  6. 最终由 s6-overlay 完成容器服务初始化

核心是最后:

exec s6-overlay-suexec \
  ' /package/admin/s6-overlay-3.2.0.2/libexec/preinit' \
  '' \
  /package/admin/s6-overlay-3.2.0.2/libexec/stage0 \
  "$@"

PUID 应该在哪里修改?

如果你的目标是:

docker run \
  -e PUID=1000 \
  -e PGID=1000 \
  your-image

让容器中的某个用户变成:

UID=1000
GID=1000

那么不要直接修改这个入口脚本

更合理的是在 /etc/cont-init.d/ 或 s6-overlay 的初始化阶段做。

例如镜像中有:

/etc/cont-init.d/10-user

可以写:

#!/command/with-contenv sh

PUID="${PUID:-1000}"
PGID="${PGID:-1000}"

groupmod -o -g "$PGID" app
usermod  -o -u "$PUID" -g "$PGID" app

然后:

docker run \
  -e PUID=1000 \
  -e PGID=1000 \
  your-image

但是这里有一个关键问题

你这个脚本是:

entrypoint
   │
   ▼
s6-overlay-suexec
   │
   ├── preinit
   │
   └── stage0
         │
         └── s6 init
              │
              ├── cont-init.d
              ├── services.d
              └── ...

所以如果你在 cont-init.d 修改 UID/GID,要确认后续 service 是以这个用户启动的

例如:

/etc/services.d/myservice/run

里面:

#!/command/with-contenv sh

exec s6-setuidgid app /usr/local/bin/myservice

这样 app 的 UID 就会使用你修改后的 PUID


如果你想实现 LinuxServer.io 那种 PUID/PGID

这种模式通常是:

-e PUID=1000
-e PGID=1000

然后:

PUID
 │
 ▼
修改 app 用户 UID
 │
 ▼
PGID
 │
 ▼
修改 app 用户 GID
 │
 ▼
s6 service
 │
 ▼
s6-setuidgid app
 │
 ▼
应用进程

例如:

#!/command/with-contenv sh

PUID="${PUID:-1000}"
PGID="${PGID:-1000}"

if getent group app >/dev/null; then
    groupmod -o -g "$PGID" app
else
    groupadd -o -g "$PGID" app
fi

if id app >/dev/null 2>&1; then
    usermod -o -u "$PUID" -g "$PGID" app
else
    useradd -o -u "$PUID" -g "$PGID" app
fi

然后应用:

exec s6-setuidgid app /app/start.sh

你这个脚本里 s6-overlay-suexec 是什么?

它不是普通的:

su

而是 s6-overlay 用来控制初始化阶段的 UID/GID 切换

你这里:

s6-overlay-suexec
    ↓
preinit
    ↓
stage0

本质上是在告诉 s6-overlay:

用特定的身份执行初始化程序,并建立后续的 s6 supervision 环境。

因此 PUID/PGID 不应该通过修改这个入口脚本实现

如果你现在是在分析一个具体的 Docker 镜像,想知道它到底在哪里读取 PUIDPGID 并修改用户 UID/GID,我可以继续帮你把 s6-overlay 3.2.0.2 的 preinit → stage0 → cont-init.d → services.d 整个启动链扒开来分析。