具有共享 X11 套接字的 Docker:为什么它可以在容器外“启动”Firefox?

cti*_*tze 6 sockets x11 firefox user-interface docker

我有以下场景:

  1. 我设置了一个可以访问 X11 套接字的 Docker 容器,基本上我是这样做的:https : //stackoverflow.com/a/25334301
  2. 然后我在容器中安装了 Firefox,并在 bash 中使用“firefox”命令启动它。

我注意到的是:如果 Firefox 在我在容器中启动它时已经在我的主机上运行,​​它本质上是“转义”容器,因为它只是打开了一个 Firefox 主机实例的新窗口。因此,它可以访问主机上的所有内容,而容器变得无用。

反之亦然:如果 Firefox 未在主机上运行,​​而我在容器中启动了一个实例,则它确实在容器内运行。如果我随后在主机上启动 Firefox,新实例也会在容器内运行。

但是,我无法使用 gvim 而不是 Firefox 重现此行为。

我很清楚 X11 套接字共享固有的安全问题,但我无法解释我上面描述的场景。为什么容器可以在其受限环境之外启动“进程”——或者更确切地说是一个窗口?我的主机系统怎么可能仅仅因为相同的程序已经在容器内运行而在容器内启动一个进程?

(请注意,我不知道如何调用除“进程”以外的程序的这种图形实例,尽管在这种情况下它可能不是真正的进程......)

系统:Ubuntu GNOME 14.10、Docker 1.5、ubuntu:最新的Docker镜像。

更新:如果我使用该-new-instance标志启动 Firefox,则不会发生这种情况,因此它似乎更像是 Firefox 问题而不是 X11 套接字问题。

更新 2:似乎这也发生在其他场景中,例如使用 ssh 和 X 转发:
https : //unix.stackexchange.com/questions/104476/why-starting-firefox-from-command-line-in- vm-starts-the-firefox-in-the-host-ma

https://superuser.com/questions/462055/launching-firefox-on-remote-server-causes-local-firefox-to-open-the-页代替

现在的问题是,Firefox 到底是怎么做到的?他们使用什么样的 X11 法术来确定 Firefox 是否已经在运行?

che*_*kow 5

因为您将 x11 套接字转发到容器中,所以任何图形程序,无论是容器内部还是容器外部,都将与同一个 Xorg 服务器通信。这与使用 ssh 和 X 转发时相同。

现在假设一个 Firefox 实例已启动并与该 xserver 进行通信。如果我们是启动的第二个 Firefox 进程,我们可能会通过从根导航窗口树来找到第一个进程。我们也许能够通过 Firefox在窗口上设置的一些属性来识别属于 Firefox 的窗口。一旦我们找到属于 Firefox 的窗口,我们可能会向拥有该窗口的进程发送一条消息,要求它添加一个新选项卡。

也许如果我们找到这样的进程并要求它打开一个新选项卡,我们就会在工作完成后死去。

当然,我们总是可以只查看源代码并发现 Firefox 确实基本上是这样做的。特别是他们:

但他们不会通过客户端消息来通知它。他们通过更改窗口属性来做到这一点。据推测,创建窗口的进程也会订阅属性更改通知。如果您好奇代码的完整路径是:

  • 从解析命令行开始,StartRemoteClient
  • 创建一个客户端(请注意,他们也通过 d-bus/wayland 执行此操作),然后调用SendCommandLine()
  • 这是一个虚函数,所以发现它覆盖了XRemoteClient
  • 在那里你可以看到它调用链接到FindBestWindow()and then的前两个函数的位置DoSendCommandLine()