替代ssh X11转发Docker容器

lor*_*age 50 user-interface docker

我正在运行一个Docker容器,主要是作为该R语言的独立开发环境.(R这里的用法与帖子的其余部分正交,即你可以假设任何可以在repl-session中运行的通用程序.)很多时候这将涉及做绘图,制作图形等内容; 我需要看看这些.因此,我更愿意选择显示我在容器中创建的图形.到目前为止,我是这样做的.首先我创建一个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"]
Run Code Online (Sandbox Code Playgroud)

我构建映像,然后使用以下命令启动容器:

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
Run Code Online (Sandbox Code Playgroud)

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

ssh -X docker@localhost -p 5000.
Run Code Online (Sandbox Code Playgroud)

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

lor*_*age 80

有一种很好的,简单的方法可以从Docker容器中获取图形输出,而无需sshd在容器内部运行守护程序.Docker可以在运行单个进程时提供裸机性能,在这种情况下应该是这样R.运行sshd守护进程虽然可能是边缘的,但​​会引入额外的开销.通过将sshd守护程序作为管理程序守护程序的子进程运行,这不会更好.当人们充分利用绑定装置时,两者都可以省去.在构建了应该运行容器的映像之后,我们启动一个交互式容器并将/tmp/.X11-unix文件夹绑定 到其中.我将陈述完整的命令并详细解释它的作用:

docker run -i -t --rm \

  • -i建立一个互动会议; -t分配伪tty; --rm使这个容器短暂

-e DISPLAY = $ DISPLAY \

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

-u码头

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

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

  • -vbind将X11驻留在/tmp/.X11-unix本地计算机上的套接字挂载到/tmp/.X11-unix容器中,:ro并使套接字只读.

--name ="rdev"ubuntu-r R

  • --name=""指定容器的名称(这里rdev); 要从(此处ubuntu-r)运行容器的图像; 要在容器中运行的进程(此处R).(只有在未设置默认值CMDENTRYPOINT图像时,才需要指定进程的最后一步.)

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

xhost +si:localuser:username
Run Code Online (Sandbox Code Playgroud)

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

这可以产生的积极影响可以从需要运行的流程数量中看出,以实现所需的目标.

(1)supervisorsshd在所述容器中运行:

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
Run Code Online (Sandbox Code Playgroud)

登录ssh并运行时R:

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
Run Code Online (Sandbox Code Playgroud)

(2)使用bind mount方法:

UID                 PID                 PPID                C                 STIME               TTY                 TIME                CMD
chb                 4356                718                 0                 18:12               pts/4               00:00:00            /usr/local/lib/R/bin/exec/R --no-save --no-restore
Run Code Online (Sandbox Code Playgroud)

  • 好东西,谢谢:-)你的解决方案与那个解决方案相比如何:http://olivier.barais.fr/blog/posts/2014.08.26/Eclipse_in_docker_container.html(不同的xhost命令,没有-u选项) (4认同)
  • 谢谢.:)简而言之:她/他通过使用容器主机名仅授予对特定可信任docker容器的访问权限.另一方面,我授予对可信用户的访问权限,从而授予他/她正在启动的所有容器.这是有效的,因为容器中的uid与主机上的uid相同. (4认同)
  • 这有两个(?)原因:(1)`-u`选项只是增加了另一层安全性.docker守护程序现在在主机上以root身份运行.因此,如果容器中的进程逃逸到主机,它可能会造成很大的破坏.如果容器中的进程作为用户进程运行,则会以某种方式迁移.(2)授予对x-socket的root访问权限不是一个好主意.用不同的方式表达:应该应用最小特权原则. (4认同)