替代ssh X11转发Docker容器

时间:2014-08-13 08:54:42

标签: user-interface docker

我正在运行Docker容器,主要是作为R语言的独立开发环境。 (这里R的用法与帖子的其余部分正交,即你可以假设任何可以在repl - 会话中运行的通用程序。)很多时候这将涉及做东西比如绘图,制作图形等;我需要看看 这些。因此,我更愿意选择显示我在容器中创建的图形。到目前为止,我是这样做的。首先,我创建一个Dockerfile。省略最重要的步骤是:

# Set root passwd 
RUN echo "root:test" | chpasswd

# Add user so that container does not run as root 
RUN useradd -m docker 
RUN echo "docker:test" | chpasswd 
RUN usermod -s /bin/bash docker 
RUN usermod -aG sudo docker 
ENV HOME /home/docker

RUN mkdir /var/run/sshd 
RUN mkdir -p /var/log/supervisor

# copy servisord.conf which lists the processes to be spawned once this 
# container is started (currently only one: sshd) 
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

EXPOSE 22 
CMD ["/usr/bin/supervisord"]

我构建图像,然后使用:

启动容器
docker run -d -p 127.0.0.1:5000:22 -h ubuntu-r -v /home/chb/files/Data:/home/docker/Data -P --name="rdev" ubuntu-r

然后可以ssh到我的容器中:

ssh -X docker@localhost -p 5000.

这会给我我想要的东西。但我想知道是否有另一种更加资源友好的方式从容器中获取图形/ GUI输出? (我希望,如果可能的话,解决方案不会涉及vnc。)

2 个答案:

答案 0 :(得分:78)

有一个很好的,简单的方法来获取图形输出 Docker容器,而不必在其中运行sshd守护进程 容器。 Docker可以在运行单个时提供裸机性能 在这种情况下应该是R的过程。运行sshd守护程序 将尽可能边际地引入额外的开销。这不是 通过将sshd守护程序作为子进程运行来改进 主管守护进程。当人们充分利用时,两者都可以省去 绑定坐骑。在构建容器所在的图像之后 要运行,我们启动一个交互式容器并绑定mount /tmp/.X11-unix文件夹。我将陈述完整的命令和 详细解释它的作用:

  

docker run -i -t --rm \

  • -i设置了一个互动会话; -t分配一个伪tty; --rm使这个容器短暂
  

-e DISPLAY = $ DISPLAY \

  • 将主机显示设置为本地计算机显示(通常为:0
  

-u docker \

  • -u指定进程应由用户(此处为docker)运行,而不是由root运行。这一步很重要(v.i。)!
  

-v /tmp/.X11-unix:/tmp/.X11-unix:ro \

  • -v bind将驻留在本地计算机上X11的{​​{1}}套接字安装到容器中的/tmp/.X11-unix/tmp/.X11-unix使套接字只读。< / LI>
  

- name =“rdev”ubuntu-r R

  • :ro指定容器的名称(此处为--name="");要从中运行容器的图像(此处为rdev);要在容器中运行的进程(此处为ubuntu-r)。 (只有在没有为图像设置默认RCMD时,才需要指定流程的最后一步。)

发出此命令后,你应该看看漂亮的ENTRYPOINT 开始输出。如果您尝试R来查看图形 输出已经工作你会注意到它不是。那是因为 demo(graphics)扩展名阻止您访问套接字。您 现在可以在您的本地计算机上键入Xsecurity并尝试xhost + 你的容器了。你现在应该有图形输出。这种方法 但是,强烈建议您禁止访问xsocket 您当前连接的任何远程主机。只要你是这样的人 与单用户系统交互这可能在某种程度上是合理的,但是 一旦涉及多个用户,这将是绝对的 不安全!因此,您应该使用危险性较小的方法。一个好方法是 使用服务器解释

demo(graphics)

可用于指定单个本地用户(请参阅xhost +si:localuser:username )。这意味着 man xhost应该是运行username服务器的用户的名称 您的本地计算机和运行docker容器的计算机。这也是 为什么在运行时指定用户很重要的原因 容器。最后但同样重要的是,总有更复杂的解决方案 使用X11xauth文件授予对.Xauthority套接字的访问权限 (见X11)。然而,这也将涉及更多的知识 man xauth如何运作。

可以在流程数量中看到这种积极影响 需要运行才能实现所需。

(1)在容器中运行Xsupervisor

sshd

通过UID PID PPID C STIME TTY TIME CMD root 4564 718 1 18:16 ? 00:00:00 /usr/bin/python /usr/bin/supervisord root 4576 4564 0 18:16 ? 00:00:00 /usr/sbin/sshd 登录并运行ssh

R

(2)使用bind mount方法:

UID                 PID                 PPID                C                 STIME               TTY                 TIME                CMD
root                4564                718                 0                 18:16               ?                   00:00:00            /usr/bin/python /usr/bin/supervisord
root                4576                4564                0                 18:16               ?                   00:00:00            /usr/sbin/sshd
root                4674                4576                0                 18:17               ?                   00:00:00            sshd: docker [priv]   
chb                 4725                4674                0                 18:18               ?                   00:00:00            sshd: docker@pts/0
chb                 4728                4725                1                 18:18               pts/0               00:00:00            -bash

答案 1 :(得分:4)

这显然是我迄今为止找到的最佳解决方案:

https://stackoverflow.com/a/25280523/1353930(所有归功于JürgenWeigert)

优点:

  • 在docker中,UID不相关(但我仍然建议使用root)
  • 在主机上,您无需更改安全设置(xhost +