用于Docker容器的ssh X11-forwarding的替代scheme

我正在运行一个Docker容器,主要是作为R语言的一个独立的开发环境。 (这里的R的用法与post的其余部分是正交的,也就是说,你可以假定任何可以在repl session中运行的通用程序)。很多时候这将涉及到做绘图,制作graphics等等的东西; 我需要看看这些。 因此,我宁愿有显示在我的容器中创build的graphics的选项。 到目前为止,我是这样做的。 首先我创build一个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. 

这会给我想要的。 但我想知道是否有另一种更容易从容器获取graphics/ GUI输出的资源? (我更喜欢,如果可能的话,解决scheme不会涉及vnc 。)

从Docker容器获取graphics输出是一种不错的和半简单的方法,无需在容器内部运行sshd守护进程。 在运行单个进程时,Docker可以提供裸机性能,在这种情况下应该是R 运行一个sshd守护进程可能会带来额外的开销。 通过运行sshd守护进程作为supervisor守护进程的subprocess,这并不是一件好事。 当使用绑定安装时,两者都可以省略。 在构build应该运行容器的映像之后,我们启动一个交互容器并绑定/tmp/.X11-unix文件夹。 我将陈述完整的命令并详细解释它的作用:

docker运行-i -t –rm \

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

-e DISPLAY = $ DISPLAY \

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

-udocker工人\

  • -u指定进程应该由用户(这里是docker )而不是root来运行。 这一步很重要(六)!

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

  • -v绑定将驻留在本地计算机上的/tmp/.X11-unix中的X11套接字挂载到/tmp/.X11-unix中的/tmp/.X11-unix:ro使得套接字只读。

–name =“rdev”ubuntu-r R

  • --name=""指定容器的名字(这里是rdev ); 你想运行容器的映像(这里是ubuntu-r ); 你想在容器中运行的过程(这里是R )。 (只有当您没有为您的图像设置默认CMDENTRYPOINT ,才需要指定过程的最后一步。)

发出这个命令后,你应该看看漂亮的R启动输出。 如果你想试试看demo(graphics)是否graphics输出已经工作,你会注意到它不是。 这是因为Xsecurity扩展阻止您访问套接字。 您现在可以在本地机器上键入xhost +并再次尝试在容器中demo(graphics) 。 你现在应该有graphics输出。 然而,这种方法是强烈的,因为你允许访问你的xsocket到你当前连接的任何远程主机。 只要你只与单用户系统交互,这可能是合理的,但只要有多个用户参与,这绝对是不安全的! 因此,你应该使用一个不太危险的方法。 一个好方法是使用解释的服务器

 xhost +si:localuser:username 

它可以用来指定一个本地用户(见man xhost )。 这意味着username应该是在本地机器上运行X11服务器并运行docker容器的用户的名字。 这也是为什么在运行容器时指定用户非常重要的原因。 最后但并非最不重要的是,总是有更复杂的解决scheme来使用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 

当通过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 

(2)用绑定安装方法:

 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 

这显然是我迄今发现的最佳解决scheme:

https://stackoverflow.com/a/25280523/1353930 (所有学分去JürgenWeigert)

优点:

  • 在docker里面,UID不相关(但是我还是build议不要使用root)
  • 在主机上,您不必更改安全设置( xhost +