如何在Linux Docker容器中运行GUI应用程序?
是否有任何图像设置vncserver或其他东西,以便您可以-例如-在Firefox周围添加额外的加速沙箱?
如何在Linux Docker容器中运行GUI应用程序?
是否有任何图像设置vncserver或其他东西,以便您可以-例如-在Firefox周围添加额外的加速沙箱?
当前回答
其他的解决方案应该可以工作,但是这里有一个docker-compose的解决方案。
要修复这个错误,您需要将$DISPLAY和. x11 -unix传递给docker,并授予启动docker的用户对xhost的访问权限。
docker-compose之内。yml文件:
version: '2'
services:
node:
build: .
container_name: node
environment:
- DISPLAY
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
在终端或脚本中:
xhost + si: localuser: $用户 xhost +当地:码头工人 出口显示= $显示 docker-compose起来
其他回答
如果您已经构建了映像,还有另一个答案:
使用sudo调用docker (如何修复docker:获得许可被拒绝的问题) 在主机和容器共享之间共享相同的USER & home & passwd (提示:使用用户id代替用户名) 驱动相关库的dev文件夹工作得很好 加上X11向前。
docker run --name=CONTAINER_NAME --network=host --privileged \
-v /dev:/dev \
-v `echo ~`:/home/${USER} \
-p 8080:80 \
--user=`id -u ${USER}` \
--env="DISPLAY" \
--volume="/etc/group:/etc/group:ro" \
--volume="/etc/passwd:/etc/passwd:ro" \
--volume="/etc/shadow:/etc/shadow:ro" \
--volume="/etc/sudoers.d:/etc/sudoers.d:ro" \
--volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
-it REPO:TAG /bin/bash
你可能会问,如果这么多东西都是一样的,那么使用docker还有什么意义呢?嗯,我能想到的一个原因是克服软件包依赖的地狱(https://en.wikipedia.org/wiki/Dependency_hell)。
所以我认为这种用法更适合开发人员。
虽然Jürgen Weigert的回答基本上涵盖了这个解决方案,但一开始我并不清楚那里描述的是什么。所以我要加上我的看法,以防有人需要澄清。
首先,相关文档是X安全性手册页。
许多在线资料都建议只挂载X11 unix套接字和~/。Xauthority文件放入容器。这些解决方案通常靠运气工作,不需要真正理解为什么,例如容器用户最终与用户拥有相同的UID,因此不需要魔术键授权。
首先,Xauthority文件的模式为0600,因此容器用户将无法读取它,除非它具有相同的UID。
即使您将文件复制到容器中,并更改了所有权,仍然存在另一个问题。如果在主机和容器上使用相同的Xauthority文件运行xauth list,您将看到列出了不同的条目。这是因为xauth根据运行位置筛选条目。
容器中的X客户端(即GUI应用程序)的行为将与xauth相同。换句话说,它看不到用户桌面上运行的X会话的神奇cookie。相反,它会看到您之前打开的所有“远程”X会话的条目(如下所述)。
所以,你需要做的是添加一个新的条目,包含容器的主机名和与主机cookie相同的十六进制键(即在你的桌面上运行的X会话),例如:
containerhostname/unix:0 MIT-MAGIC-COOKIE-1 <shared hex key>
问题是cookie必须在容器中添加xauth add:
touch ~/.Xauthority
xauth add containerhostname/unix:0 . <shared hex key>
否则,xauth将以一种只能在容器外部看到的方式标记它。
该命令的格式为:
xauth add hostname/$DISPLAY protocol hexkey
在哪里。表示MIT-MAGIC-COOKIE-1协议。
注意:不需要复制或绑定挂载. xauthority到容器中。只需创建一个空白文件,如图所示,并添加cookie。
Jürgen Weigert的答案通过使用FamilyWild连接类型在主机上创建一个新的权限文件并将其复制到容器中来解决这个问题。注意,它首先从~/中提取当前X会话的十六进制键。使用xauth nlist。
所以基本步骤是:
提取用户当前X会话的cookie的十六进制键。 在容器中创建一个新的Xauthority文件,使用容器主机名和共享的十六进制密钥(或创建一个具有FamilyWild连接类型的cookie)。
我承认我不是很了解FamilyWild是如何工作的,也不是很了解xauth或X客户机是如何根据运行位置从Xauthority文件中过滤条目的。欢迎提供这方面的更多信息。
如果你想要分发Docker应用,你需要一个启动脚本来运行容器,该容器为用户的X会话获取十六进制密钥,并以前面解释的两种方式之一将其导入容器。
它还有助于理解授权过程的机制:
在容器中运行的X客户机(即GUI应用程序)在Xauthority文件中查找与容器的主机名和$DISPLAY值匹配的cookie条目。 如果找到匹配的条目,X客户端将其与授权请求一起通过/tmp/. xml目录中的适当套接字传递给X服务器。X11-unix目录挂载在容器中。
注意:X11 Unix套接字仍然需要挂载在容器中,否则容器将没有到X服务器的路由。出于安全原因,大多数发行版默认禁用对X服务器的TCP访问。
为了获得更多信息,并更好地掌握X客户端/服务器关系是如何工作的,查看SSH X转发的示例案例也很有帮助:
The SSH server running on a remote machine emulates its own X server. It sets the value of $DISPLAY in the SSH session to point to its own X server. It uses xauth to create a new cookie for the remote host, and adds it to the Xauthority files for both the local and remote users. When GUI apps are started, they talk to SSH's emulated X server. The SSH server forwards this data back to the SSH client on your local desktop. The local SSH client sends the data to the X server session running on your desktop, as if the SSH client was actually an X client (i.e. GUI app). The X server uses the received data to render the GUI on your desktop. At the start of this exchange, the remote X client also sends an authorization request, using the cookie that was just created. The local X server compares it with its local copy.
这不是轻量级的,但是一个很好的解决方案,使docker特性与完整的桌面虚拟化相同。Ubuntu和CentOS的Xfce4或IceWM都可以工作,noVNC选项可以通过浏览器轻松访问。
https://github.com/ConSol/docker-headless-vnc-container
它运行noVNC以及tigerVNC的vncserver。然后它为给定的窗口管理器调用startx。此外,libss_wrapper . dll。用于模拟用户的密码管理。
我刚刚发现了这篇博客,想在这里与你们分享,因为我认为这是最好的方法,而且很简单。
http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/
优点: + docker容器中没有x服务器的东西 +不需要VNC客户端/服务器 + SSH不支持x转发 +更小的docker容器
缺点: 在主机上使用x(不是为了安全沙箱)
以防链接有一天会失败,我把最重要的部分放在这里: dockerfile:
FROM ubuntu:14.04
RUN apt-get update && apt-get install -y firefox
# Replace 1000 with your user / group id
RUN export uid=1000 gid=1000 && \
mkdir -p /home/developer && \
echo "developer:x:${uid}:${gid}:Developer,,,:/home/developer:/bin/bash" >> /etc/passwd && \
echo "developer:x:${uid}:" >> /etc/group && \
echo "developer ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/developer && \
chmod 0440 /etc/sudoers.d/developer && \
chown ${uid}:${gid} -R /home/developer
USER developer
ENV HOME /home/developer
CMD /usr/bin/firefox
构建映像:
docker build -t firefox .
run命令:
docker run -ti --rm \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
firefox
当然,你也可以在运行命令中使用sh -c "echo script-here"
提示:音频请查看:https://stackoverflow.com/a/28985715/2835523
如果你想无头运行GUI应用程序,请阅读这里。您需要做的是使用xvfb或其他类似软件创建一个虚拟监视器。如果您想在浏览器上运行Selenium测试,这是非常有用的。
任何地方都没有提到的是,一些软件实际上本身就在Linux容器中使用沙盒。例如,如果你在运行容器时没有使用适当的特权标志,Chrome将永远不会正常运行。