配置
本机
- 安装并运行 X 服务器:
- Linux:自带(Xorg/Wayland+XWayland),无需额外安装。
- macOS:安装并启动 XQuartz。
- Windows:安装并启动 VcXsrv(建议 -multiwindow -clipboard;如有问题可先勾“Disable access control”测试)。
- 记得设置环境变量 DISPLAY = “127.0.0.1:0.0”,含义
- 127.0.0.1:X 服务器所在主机(你的本机,Windows 上运行的 VcXsrv)
- 0:display number(第几个 X 服务器实例,从 0 起)
- .0:screen number(该 X 服务器里的第几个“屏幕”,从 0 起)
- 记得设置环境变量 DISPLAY = “127.0.0.1:0.0”,含义
- 在本机终端(不是 VS Code)执行: ssh -Y user@remote ‘echo $DISPLAY; which xauth; xclock’ 预期:
- 打印出类似 localhost:10.0 的 DISPLAY,并弹出 xclock 窗口。
- 如果提示 xauth not found 或 Can’t open display,则继续下述远端主机的配置
远端
- 安装 xauth 和测试程序:
- Debian/Ubuntu:sudo apt-get update && sudo apt-get install -y xauth x11-apps
- RHEL/CentOS:sudo yum install -y xorg-x11-xauth xclock
- 确认 /etc/ssh/sshd_config:
- 必须有:X11Forwarding yes
- 可选更宽松(一般不需要):X11UseLocalhost yes(保持默认即可)
- 查看生效配置:sudo sshd -T | grep -i x11
- 修改后重启 sshd:sudo systemctl restart sshd 或 sudo service ssh restart
- 再用步骤 1 的 ssh -Y 命令验证一次,直到能弹出 xclock。
步骤
分几种情况:
GUI 程序在远端系统环境下跑,界面在本地显示
按如上配置好即可通过 ssh 终端运行
GUI 程序在远端容器里跑,界面在本地显示
- 允许容器访问你的 X11(比 xhost + 更安全)
xhost +si:localuser:root # 如果容器里用 root 运行
# 或者让容器以当前用户运行,就改为:
xhost +si:localuser:$USERNote
这里貌似必须在宿主机上运行 xhost 命令,通过 ssh 终端运行会提示 xhost: unable to open display ""
- 启动容器
docker run -dit --name umi-dev -v .:`pwd` -w `pwd` -v /tmp/.X11-unix:/tmp/.X11-unix:rw --ipc=host --network=host umi:dev注:—ipc=host 表示让容器与宿主机共享同一个 IPC 命名空间(Inter-Process Communication)。这样容器里的进程可以和宿主机通过 IPC 机制互通,例如 POSIX 共享内存、消息队列、信号量,以及共享宿主机的 /dev/shm。
- VSCode 附加到远端机器的容器,打开 VSCode 终端即可运行 GUI 程序
原理
- X11(X Window System)是一套“网络透明”的图形窗口系统:真正控制显示器/键鼠的是本地的 X Server,应用程序是 X Client,可以在远端运行,把“画图/事件”协议通过网络发给本地的 X Server 来绘制窗口。
- 你在 VS Code 里附加到远端容器后,终端里启动的 GUI 能在本机显示,核心就是“X11 转发”。通常是通过 SSH 的 X11 转发把远端(容器内)的 X Client 流量,经由隧道回送到你本机的 X Server(Linux 的 Xorg/XWayland,macOS 的 XQuartz,Windows 的 VcXsrv 等)来渲染。
工作原理(数据流)
- 本机运行一个 X Server(Xorg/XWayland、XQuartz、VcXsrv 等)。
- VS Code Remote-SSH 建立到远端主机的 SSH 连接,并开启 X11 转发(设置里有 Remote.SSH: Enable X11 Forwarding)。SSH 会:
- 在远端生成一个“伪 X 服务器端口”(通常把 DISPLAY 设成 localhost:10.0 这样的地址/显示号)。
- 在远端写入匹配的 Xauthority cookie(访问控制用)。
- 把该端口的 X11 协议流量通过 SSH 隧道转回本机,并注入到你本机的 X Server。
- 你再从 VS Code 里“附加到容器”。VS Code(Dev Containers/Attach)通常会把远端主机上的 DISPLAY、XAUTHORITY 等环境传递到容器里,或以等效方式让容器能连到前述“伪 X 服务器”。
- 你在容器内启动 GUI 程序(X Client):
- 程序读取 DISPLAY(如 localhost:10.0),连接到远端主机上的 SSH 转发端口;
- SSH 把 X11 协议转回你的本机;
- 本机的 X Server 负责实际绘制窗口、处理键鼠,事件再经隧道回传给远端程序。
你能看到它“无感”工作的关键
- DISPLAY:告诉 X Client 要连哪个 X Server(示例:localhost:10.0)。
- XAUTHORITY(xauth cookie):X Server 的访问控制凭证,防止未授权连接。
- VS Code Remote-SSH 开了 X11 转发并把这些环境传到容器里,因此容器内的 GUI 也能复用这条隧道。
如何自检/排查
- 在容器里 echo $DISPLAY,常见值像 localhost:10.0 或 :10.0。
- 看有没有 xauth:echo $XAUTHORITY 或 xauth list。
- 本机必须有 X Server(Linux 自带;mac 需 XQuartz;Windows 需 VcXsrv 等),并且允许连接。
- 若遇到 MIT-SHM 报错或空白窗口,可尝试:
- 设环境变量:QT_X11_NO_MITSHM=1
- 或(在 Docker 场景)用 —ipc=host 或增大 /dev/shm(—shm-size=2g)
补充
- 如果你的本机是 Wayland 桌面,X 应用会通过本机的 XWayland 转给 Wayland 合成器显示,机制对你是透明的。
- X11 协议延迟敏感,跨网络图形可能卡顿;3D/视频类应用性能受限是正常现象。