Docker下Xvfb与x11vnc指定不同显示号连接显示内容相同
故障根因
这是host网络模式下X11服务的套接字访问逻辑,叠加单docker-compose部署的默认资源共享规则导致的,和镜像本身功能无关:
- Xvfb启动后默认提供两种接入方式:一是基于TCP端口
6000+显示号的网络接入,二是基于Unix域套接字/tmp/.X11-unix/X<显示号>的本地接入,x11vnc连接X服务时默认优先走Unix域套接字。 - 同一份docker-compose文件启动的服务如果没有显式配置,默认会共享项目级IPC命名空间,加上host网络模式下所有容器共享宿主机网络栈,只要两个容器的
/tmp目录没有做完全隔离,后启动容器内的x11vnc查找对应显示号的套接字时,会直接命中先启动容器创建的Xvfb套接字。最终两个x11vnc进程虽然分别绑定了5900、5901两个RFB端口,后端实际都连到了同一个Xvfb实例上,自然看到的桌面内容完全一致。 - 拆分为两个独立compose文件启动时,两个compose项目的IPC资源、容器文件系统完全隔离,x11vnc只能连接到自身容器内启动的Xvfb,因此隔离正常。
- 启动日志显示x11vnc绑定了指定显示号属于正常现象:x11vnc启动时仅校验DISPLAY参数的格式合法性,不会校验连接到的X服务实际属于哪个进程/容器,因此不会抛出错误。
正确配置方案
不需要拆分compose文件,在原单compose配置基础上做少量调整即可解决问题:
- 为每个服务显式声明独立IPC命名空间,禁止同compose下服务共享IPC资源
- 为每个容器的
/tmp、/run目录挂载独立tmpfs临时文件系统,彻底隔离X11套接字、锁文件的访问路径 - 调整镜像内启动脚本参数,强制Xvfb关闭TCP监听、x11vnc仅通过本地Unix套接字连接Xvfb,避免跨实例访问
修正后的docker-compose.yml参考配置
version: '3.8' services: selenium-node-90: build: ./custom-selenium-node # 替换为你自己的镜像构建路径或镜像名 network_mode: host # 关键配置:独立IPC命名空间 ipc: private environment: - DISPLAY=:90 - VNC_PORT=5900 # 关键配置:独立临时文件系统,隔离X11套接字与锁文件 tmpfs: - /tmp - /run restart: unless-stopped selenium-node-91: build: ./custom-selenium-node network_mode: host ipc: private environment: - DISPLAY=:91 - VNC_PORT=5901 tmpfs: - /tmp - /run restart: unless-stopped
镜像内启动脚本调整参考
将镜像内部Xvfb、x11vnc的启动命令替换为如下格式,从进程层面杜绝跨容器连接:
# 启动Xvfb,关闭TCP监听,指定分辨率 Xvfb $DISPLAY -screen 0 1920x1080x24 -nolisten tcp -noreset & # 等待Xvfb就绪 sleep 2 # 启动x11vnc,强制走Unix套接字连接本地Xvfb,显式指定VNC端口 x11vnc -display $DISPLAY -rfbport $VNC_PORT -shared -forever -unixsock -nopw &
效果验证
配置修改后重新启动容器,可通过两步确认隔离生效:
- 分别进入两个容器执行
ss -xpl | grep X11-unix,每个容器内只能看到自身对应显示号的Xvfb套接字,看不到另一个显示号的套接字记录 - 分别连接5900、5901端口,在其中一个桌面内做任意操作(比如打开浏览器、新建文本文件),另一个桌面不会出现同步变化。
内容的提问来源于stack exchange,提问作者Magda Muffin
相关产品推荐
相关产品推荐

