Github开源生信云平台 DEMO
Read memory
Created memory file
黑屏跟 --user $(id -u):$(id -g) 无关,是宿主机 Docker 默认 seccomp 拦截了 close_range 系统调用,导致容器里 Xfce 桌面组件全部启动失败。
--user $(id -u):$(id -g)
close_range
1. VNC 本身是好的 —— Xvnc 和 noVNC 都正常起来了:
Xtigervnc :1 -rfbport 5901 -geometry 1920x1080 -depth 24 # 在跑 python3 -m websockify ... 6901 localhost:5901 # 在跑
所以你连上 6901 后能看到画面(而不是连不上)——只是画面里只有一块空白的根窗口 = 黑屏。
2. 桌面是空的 —— ps 里只有 xfce4-session,关键组件一个都没有:
ps
xfce4-session
46 xfce4-session # 在 # ❌ 没有 xfwm4 / xfce4-panel / xfdesktop / xfsettingsd
3. wm_startup.log 里找到了根因:
wm_startup.log
(xfce4-session:158): Unable to launch "xfsettingsd" ...: Failed to close file descriptor for child process (Operation not permitted) (xfce4-session:158): Unable to launch "light-locker" ...: 同上 (xfce4-session:158): Unable to launch "xiccd" ...: 同上 (xfce4-session:158): Unable to launch xfce4-notifyd ...: 同上 (xfce4-session:158): Unable to launch polkit-gnome-...: 同上
xfce4-session 启动任何子进程都失败了 → 没有窗口管理器、没有面板、没有桌面图标 → 黑屏。
GLib 的 g_spawn 会调用 Linux 5.9+ 才有的 close_range(2) 来关闭子进程的文件描述符。实测你这台机器:
g_spawn
close_range(2)
--security-opt seccomp=unconfined
原因链:你的 Docker 是 20.10.18,内核 5.4.0-26,而 Ubuntu 20.04 的 libseccomp < 2.5.0 不认识 close_range 这个名字 → Docker 默认 profile 里那条 allow 规则被静默丢弃 → 未匹配的 syscall 按 SCMP_ACT_ERRNO(EPERM) 处理 → 返回 EPERM。而 GLib 只在 ENOSYS 时优雅回退,遇到 EPERM 直接硬失败,于是每个 g_spawn 都挂。
20.10.18
5.4.0-26
libseccomp < 2.5.0
SCMP_ACT_ERRNO(EPERM)
顺带验证:不加 --user(用镜像默认 uid 1000)同样是 EPERM,所以 --user 不是元凶——这个镜像本来就靠 nss_wrapper(generate_container_user + LD_PRELOAD)支持任意 UID。
--user
nss_wrapper
generate_container_user
LD_PRELOAD
加上 --security-opt seccomp=unconfined:
docker run --rm --user $(id -u):$(id -g) \ --security-opt seccomp=unconfined \ -p 6901:6901 \ -e VNC_RESOLUTION=1920x1080 \ -e VNC_PASSWORDLESS=true \ registry.cn-hangzhou.aliyuncs.com/wybioinfo/debian-xfce-vnc
验证结果 —— 桌面组件全部正常:
139 xfwm4 161 xfsettingsd 164 xfce4-panel 173 xfdesktop
备选方案:宿主机把 libseccomp2 升到 ≥ 2.5.0(focal-updates 有)并重启 docker,这样那条 allow 规则生效,close_range 在 5.4 内核上返回 ENOSYS,GLib 就能正常回退——比 unconfined 更安全;或者自备一份允许 close_range 的 seccomp profile。
libseccomp2
focal-updates
修复后日志里剩下的这些是无害噪音,不用管(容器内没有 systemd / system D-Bus / pulseaudio):
could not get proxy for org.freedesktop.login1
light-locker: session_id is not set
polkit-gnome: Could not connect
pa_context_connect() failed
我已把这条环境陷阱记进仓库记忆 docker-runtime-notes.md,后续遇到容器内 GTK/Python GUI 程序莫名起不来可以直接查。
docker-runtime-notes.md