你能在docker容器中运行GUI应用程序吗?

时间:2022-05-08 20:45:35

How can you run GUI apps in a docker container?

如何在docker容器中运行GUI应用程序?

Are there any images that set up vncserver or something so that you can - for example - add an extra speedbump sandbox around say Firefox?

是否有一些图像设置了vncserver或其他什么东西以便你可以-例如-添加一个额外的速度缓冲沙箱周围说火狐?

16 个解决方案

#1


182  

You can simply install a vncserver along with firefox :)

您可以简单地安装一个vncserver和firefox:)

I pushed an image vnc/firefox here: docker pull creack/firefox-vnc

我在这里推了一个图像vnc/firefox: docker拉creack/firefox-vnc。

The image has been made with this Dockerfile:

这张图片是用这个Dockerfile做的:

# Firefox over VNC
#
# VERSION               0.1
# DOCKER-VERSION        0.2

FROM    ubuntu:12.04
# Make sure the package repository is up to date
RUN     echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN     apt-get update

# Install vnc, xvfb in order to create a 'fake' display and firefox
RUN     apt-get install -y x11vnc xvfb firefox
RUN     mkdir ~/.vnc
# Setup a password
RUN     x11vnc -storepasswd 1234 ~/.vnc/passwd
# Autostart firefox (might not be the best way to do it, but it does the trick)
RUN     bash -c 'echo "firefox" >> /.bashrc'

This will create a docker container running vnc with the password 1234:

这将创建一个运行vnc的docker容器,密码为1234:

For docker version 1.3 or newer:

对于docker 1.3或更新版本:

docker run -p 5900 -e HOME=/ creack/firefox-vnc x11vnc -forever -usepw -create

docker运行- p5900 -e HOME=/ creack/firefox-vnc x11vnc -永远-usepw -create。

For docker before version 1.3:

在1.3版之前的docker:

docker run -p 5900 creack/firefox-vnc x11vnc -forever -usepw -create

docker运行- p5900 creack/firefox-vnc x11vnc -永远-usepw -create。

#2


150  

Xauthority becomes an issue with newer systems. I can either discard any protection with xhost + before running my docker containers, or I can pass in a well prepared Xauthority file. Typical Xauthority files are hostname specific. With docker, each container can have a different host name (set with docker run -h), but even setting the hostname of the container identical to the host system did not help in my case. xeyes (I like this example) simply would ignore the magic cookie and pass no credentials to the server. Hence we get an error message 'No protocol specified Cannot open display'

Xauthority成为新系统的一个问题。在运行docker容器之前,我可以使用xhost +来丢弃任何保护,或者我可以传入一个准备良好的Xauthority文件。典型的Xauthority文件是特定于主机名的。对于docker,每个容器都可以有一个不同的主机名(设置docker run -h),但即使设置与主机系统相同的容器的主机名也不能对我的情况有所帮助。xeyes(我喜欢这个例子)只是忽略了神奇的cookie,并没有向服务器传递任何凭据。因此,我们得到一个错误消息'没有指定的协议不能打开显示'

The Xauthority file can be written in a way so that the hostname does not matter. We need to set the Authentication Family to 'FamilyWild'. I am not sure, if xauth has a proper command line for this, so here is an example that combines xauth and sed to do that. We need to change the first 16 bits of the nlist output. The value of FamilyWild is 65535 or 0xffff.

Xauthority文件可以以某种方式写入,以便主机名不重要。我们需要将身份验证家族设置为“FamilyWild”。我不确定,如果xauth有一个合适的命令行,那么这里有一个结合xauth和sed的例子。我们需要更改nlist输出的前16位。FamilyWild的价值是65535或0xffff。

docker build -t xeyes - << __EOF__
FROM debian
RUN apt-get update
RUN apt-get install -qqy x11-apps
ENV DISPLAY :0
CMD xeyes
__EOF__
XSOCK=/tmp/.X11-unix
XAUTH=/tmp/.docker.xauth
xauth nlist :0 | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
docker run -ti -v $XSOCK:$XSOCK -v $XAUTH:$XAUTH -e XAUTHORITY=$XAUTH xeyes

#3


46  

With docker data volumes it's very easy to expose xorg's unix domain socket inside the container.

通过docker的数据量,很容易在容器内公开xorg的unix域套接字。

For example, with a Dockerfile like this:

例如,使用这样的Dockerfile:

FROM debian
RUN apt-get update
RUN apt-get install -qqy x11-apps
ENV DISPLAY :0
CMD xeyes

You could do the following:

你可以这样做:

$ docker build -t xeyes - < Dockerfile
$ XSOCK=/tmp/.X11-unix/X0
$ docker run -v $XSOCK:$XSOCK xeyes

This of course is essentially the same as X-forwarding. It grants the container full access to the xserver on the host, so it's only recommended if you trust what's inside.

当然这和x -转发是一样的。它允许容器在主机上完全访问xserver,所以只有在您信任内部的情况时才建议使用它。

Note: If you are concerned about security, a better solution would be to confine the app with mandatory- or role-based-access control. Docker achieves pretty good isolation, but it was designed with a different purpose in mind. Use AppArmor, SELinux, or GrSecurity, which were designed to address your concern.

注意:如果你担心安全问题,更好的解决方案是用强制性的或基于角色的访问控制来限制应用程序。Docker实现了非常好的隔离,但是它的设计目的是不同的。使用设备,SELinux或GrSecurity,这是用来解决您的问题的。

#4


46  

i just found this blog entry and want to share it here with you because i think it is the best way to do it and it is so easy.

我刚找到这个博客,想和你分享它,因为我认为这是最好的方法,而且很容易。

http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/

http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/

PROS:
+ no x server stuff in the docker container
+ no vnc client/server needed
+ no ssh with x forwarding
+ much smaller docker containers

优点:在docker容器中没有x服务器的东西+没有vnc客户端/服务器需要+没有x转发的ssh +更小的docker容器。

CONS:
- using x on the host (not meant for secure-sandboxing)

缺点:-在主机上使用x(不是为了安全沙箱)

in case the link will fail some day i have put the most important part here:
dockerfile:

万一链接失败,我把最重要的部分放在这里: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

build the image:

构建图像:

docker build -t firefox .

and the run command:

运行命令:

docker run -ti --rm \
   -e DISPLAY=$DISPLAY \
   -v /tmp/.X11-unix:/tmp/.X11-unix \
   firefox

of course you can also do this in the run command with sh -c "echo script-here"

当然你也可以在run命令中使用sh -c "echo script-here"

HINT: for audio take a look at: https://*.com/a/28985715/2835523

提示:对于音频,请查看:https://*.com/a/28985715/2835523。

#5


23  

You can also use subuser: https://github.com/timthelion/subuser

您也可以使用subuser: https://github.com/timthelion/subuser。

This allows you to package many gui apps in docker. Firefox and emacs have been tested so far. With firefox, webGL doesn't work though. Chromium doesn't work at all.

这允许您在docker中打包许多gui应用程序。Firefox和emacs已经进行了测试。而对于firefox, webGL并没有发挥作用。铬根本不起作用。

EDIT: Sound works!

编辑:良好的工作!

EDIT2: In the time since I first posted this, subuser has progressed greatly. I now have a website up subuser.org, and a new security model for connecting to X11 via XPRA bridging.

在我发布这篇文章的时候,subuser已经有了很大的进步。我现在有一个网站subuser.org,和一个新的安全模型连接到X11通过XPRA桥接。

#6


19  

OSX

Jürgen Weigert has the best answer that worked for me on Ubuntu, however on OSX, docker runs inside of VirtualBox and so the solution doesn't work without some more work.

Jurgen Weigert在Ubuntu上为我提供了最好的答案,但是在OSX上,docker在VirtualBox中运行,所以解决方案在没有更多工作的情况下无法工作。

I've got it working with these additional ingredients:

我用了这些额外的材料:

  1. Xquartz (OSX no longer ships with X11 server)
  2. Xquartz (OSX不再带有X11服务器)
  3. socket forwarding with socat (brew install socat)
  4. 用socat (brew安装socat)
  5. bash script to launch the container
  6. bash脚本启动容器。

I'd appreciate user comments to improve this answer for OSX, I'm not sure if socket forwarding for X is secure, but my intended use is for running the docker container locally only.

我希望用户评论能改进OSX的这个答案,我不确定是否为X的套接字转发是安全的,但是我的目的是只在本地运行docker容器。

Also, the script is a bit fragile in that it's not easy to get the IP address of the machine since it's on our local wireless so it's always some random IP.

另外,这个脚本有点脆弱,因为它是在我们本地的无线网络上,所以很难得到机器的IP地址,所以它总是一些随机的IP。

The BASH script I use to launch the container:

我用来启动容器的BASH脚本:

#!/usr/bin/env bash

CONTAINER=py3:2016-03-23-rc3
COMMAND=/bin/bash
NIC=en0

# Grab the ip address of this box
IPADDR=$(ifconfig $NIC | grep "inet " | awk '{print $2}')

DISP_NUM=$(jot -r 1 100 200)  # random display number between 100 and 200

PORT_NUM=$((6000 + DISP_NUM)) # so multiple instances of the container won't interfer with eachother

socat TCP-LISTEN:${PORT_NUM},reuseaddr,fork UNIX-CLIENT:\"$DISPLAY\" 2>&1 > /dev/null &

XSOCK=/tmp/.X11-unix
XAUTH=/tmp/.docker.xauth.$USER.$$
touch $XAUTH
xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -

docker run \
    -it \
    --rm \
    --user=$USER \
    --workdir="/Users/$USER" \
    -v "/Users/$USER:/home/$USER:rw" \
    -v $XSOCK:$XSOCK:rw \
    -v $XAUTH:$XAUTH:rw \
    -e DISPLAY=$IPADDR:$DISP_NUM \
    -e XAUTHORITY=$XAUTH \
    $CONTAINER \
    $COMMAND

rm -f $XAUTH
kill %1       # kill the socat job launched above

I'm able to get xeyes and matplotlib working with this approach.

我可以用这种方法得到xeyes和matplotlib。

Windows 7+

It's a bit easier on Windows 7+ with MobaXterm:

在Windows 7+中使用MobaXterm比较容易:

  1. Install MobaXterm for windows
  2. 为windows安装MobaXterm
  3. Start MobaXterm
  4. 开始MobaXterm
  5. Configure X server: Settings -> X11 (tab) -> set X11 Remote Access to full
  6. 配置X服务器:设置-> X11 (tab) ->设置X11远程访问。
  7. Use this BASH script to launch the container
  8. 使用此BASH脚本启动容器。

run_docker.bash:

run_docker.bash:

#!/usr/bin/env bash

CONTAINER=py3:2016-03-23-rc3
COMMAND=/bin/bash
DISPLAY="$(hostname):0"
USER=$(whoami)

docker run \
    -it \
    --rm \
    --user=$USER \
    --workdir="/home/$USER" \
    -v "/c/Users/$USER:/home/$USER:rw" \
    -e DISPLAY \
    $CONTAINER \
    $COMMAND

你能在docker容器中运行GUI应用程序吗?

#7


17  

Here's a lightweight solution that avoids having to install any X server, vnc server or sshd daemon on the container. What it gains in simplicity it loses in security and isolation.

这里有一个轻量级的解决方案,可以避免在容器上安装任何X服务器、vnc服务器或sshd守护进程。它在简单中获得的好处在安全和隔离中失去了。

It assumes that you connect to the host machine using ssh with X11 forwarding.

它假定您使用ssh与X11转发连接到主机。

In the sshd configuration of the host, add the line

在主机的sshd配置中,添加一行。

X11UseLocalhost no

So that the forwarded X server port on the host is opened on all interfaces (not just lo) and in particular on the Docker virtual interface, docker0.

因此,主机上转发的X服务器端口在所有接口上都打开(不只是lo),尤其是在Docker虚拟接口上,docker0。

The container, when run, needs access to the .Xauthority file so that it can connect to the server. In order to do that, we define a read-only volume pointing to the home directory on the host (maybe not a wise idea!) and also set the XAUTHORITY variable accordingly.

在运行时,容器需要访问. xauthority文件,以便它可以连接到服务器。为了做到这一点,我们定义一个只读的量,指向主机上的主目录(可能不是一个明智的主意!),并相应地设置XAUTHORITY变量。

docker run -v $HOME:/hosthome:ro -e XAUTHORITY=/hosthome/.Xauthority

That is not enough, we also have to pass the DISPLAY variable from the host, but substituting the hostname by the ip:

这还不够,我们还必须从主机传递显示变量,但要用ip替换主机名:

-e DISPLAY=$(echo $DISPLAY | sed "s/^.*:/$(hostname -i):/")

We can define an alias:

我们可以定义一个别名:

 alias dockerX11run='docker run -v $HOME:/hosthome:ro -e XAUTHORITY=/hosthome/.Xauthority -e DISPLAY=$(echo $DISPLAY | sed "s/^.*:/$(hostname -i):/")'

And test it like this:

然后像这样测试:

dockerX11run centos xeyes

#8


10  

Sharing host display :0, as stated in some other answers, has two drawbacks:

共享主机显示:0,如其他答案所述,有两个缺点:

  • It breaks container isolation due to some X security leaks. For example, keylogging with xev or xinput is possible.
  • 由于某些X安全漏洞,它打破了容器隔离。例如,使用xev或xinput进行键盘记录是可能的。
  • Applications can have rendering glitches and bad RAM access errors due to missing shared memory for X extension MIT-SHM.
  • 由于对X扩展mitshm缺少共享内存,应用程序可能会出现故障和错误的RAM访问错误。

To circumvent X security leaks and to avoid MIT-SHM issue, I have published x11docker on github. The main idea is to run a second X server with its own authentication cookies and with MIT-SHM disabled. docker containers get access to the new X server and are segregated from host display :0. There are no X dependencies inside the image as X / Xephyr is provided by host.

为了规避X安全漏洞,并避免MIT-SHM问题,我在github上发布了x11docker。主要的想法是使用自己的身份验证cookie运行第二个X服务器,并禁用mitshm。docker容器可以访问新的X服务器,并与主机显示隔离:0。当X / Xephyr由主机提供时,图像中没有X依赖项。

Below an example script to run a docker image in Xephyr. It expects some arguments, first a host window manager to run in Xephyr, second a docker image, optionally third an image command to be executed. To run a desktop environment in docker, use ":" instead of a host window manager. On systems without a root password, change variable $Getroot

下面是在Xephyr中运行docker映像的示例脚本。它需要一些参数,首先是一个主机窗口管理器,它运行在Xephyr中,第二个是docker镜像,可选第三个要执行的图像命令。要在docker中运行桌面环境,请使用“:”而不是主机窗口管理器。在没有根密码的系统上,更改变量$Getroot。

Xephyr is started using xinit. A custom xinitrc is created to create a cookie, to set keyboard layout, to run window manager, and to run xterm with xtermrc to prompt for password to run docker.

Xephyr开始使用xinit。创建一个自定义xinitrc来创建一个cookie,设置键盘布局,运行窗口管理器,并使用xtermrc运行xterm,以提示密码运行docker。

Closing Xephyr window terminates docker container applications. Terminating the dockered applications closes Xephyr window.

关闭Xephyr窗口会终止docker容器应用程序。终止docker应用程序关闭Xephyr窗口。

Annotations:

注释:

  • The MIT-SHM problem also can be avoided with docker option --ipc=host, but this breaks down container isolation and is discouraged.
  • 也可以使用docker选项——ipc=主机来避免MIT-SHM问题,但是这打破了容器的隔离,并且是不鼓励的。
  • The cookie has to be changed to "familiy wild" as described by @Jürgen Weigert if shared X socket is used. With X over tcp, this is not needed.
  • 如果使用共享的X套接字,则必须将cookie更改为“familiy wild”,如@Jurgen Weigert所述。对于X / tcp,这是不需要的。
  • similar solutions are possible with Xpra, Xorg and Xvnc
  • Xpra、Xorg和Xvnc也有类似的解决方案。
  • For X over tcp, find out docker daemon ip (mostly 172.17.42.1), share DISPLAY=172.17.42.1:1, create cookie for it, don't share NewXsocket and don't use X/Xephyr option -nolisten tcp. Using X over tcp, MIT-SHM is disabled automatically.
  • 对于X/ tcp,查找docker守护进程ip(主要是172.17.42.1),共享显示=172.17.42.1:1,为它创建cookie,不要共享NewXsocket,也不要使用X/Xephyr选项-nolisten tcp。在tcp上使用X, MIT-SHM被自动禁用。

Examples:

例子:

  • x11docker_example "openbox --sm-disable" x11docker/lxde pcmanfm
  • x11docker_example“openbox—sm-disable”x11docker/lxde pcmanfm。
  • x11docker_example : x11docker/lxde
  • x11docker_example:x11docker /插件

x11docker_example script:

x11docker_example脚本:

#! /bin/bash
# x11docker_example : Example script to run docker GUI applications in Xephyr.
#                     Look at x11docker on github: https://github.com/mviereck/x11docker
#
# Usage:
#   x11docker_example WINDOWMANAGER DOCKERIMAGE [IMAGECOMMAND [ARGS]]
#
# WINDOWMANAGER     host window manager for use with single GUI applications.
#                   To run a desktop environment in docker, use ":"
# DOCKERIMAGE       docker image containing GUI applications or a desktop
# IMAGECOMMAND      command to run in image
#
Windowmanager="$1" && shift
Dockerimage="$*"

# command to get root permissions to run docker
Getroot="su -c"
# Getroot="sudo su -c"      # Use this on systems without a root password like Ubuntu or Sparky

# define new display and its X socket.
Newdisplay=:1
# To make sure $Newdisplay is not already in use, check /tmp/.Xn-lock
[ -e "/tmp/.X1-lock" ] && echo "Error: Display :1 is already in use" >&2 && exit 1
NewXsocket=/tmp/.X11-unix/X1


# cache folder and files
Cachefolder=/tmp/x11docker_example
mkdir -p $Cachefolder
Xclientcookie=$Cachefolder/Xcookie.client
Xservercookie=$Cachefolder/Xcookie.server
Xtermrc=$Cachefolder/xtermrc
Xinitrc=$Cachefolder/xinitrc
Dockerpidfile=$Cachefolder/docker.pid
Dockerlogfile=$Cachefolder/docker.log


# command to run docker
# --rm                           created container will be discarded.
# -e DISPLAY=$Newdisplay         set environment variable to new display
# -e XAUTHORITY=/Xcookie         set environment variable XAUTHORITY to provided cookie
# -v $Xclientcookie:/Xcookie:ro  provide cookie file to container
# -v $NewXsocket:$NewXsocket:ro  Share new X socket of Xephyr
Dockercommand="docker run --rm -e DISPLAY=$Newdisplay -e XAUTHORITY=/Xcookie -v $Xclientcookie:/Xcookie:ro -v $NewXsocket:$NewXsocket:ro $Dockerimage"  


# command to run X/Xephyr
# /usr/bin/Xephyr                an absolute path to X server executable must be given
# $Newdisplay                    first argument has to be new display
# -auth $Xservercookie           path to cookie file for X server. Must be different from cookie file of client, not sure why
# -nolisten tcp                  disable tcp connections for security reasons
# -extension MIT-SHM             disable MIT-SHM to avoid rendering glitches and bad RAM access (+ instead of - enables it)
# -retro                         nice retro look
Xcommand="/usr/bin/Xephyr $Newdisplay -auth $Xservercookie -nolisten tcp -extension MIT-SHM -retro"


# create xinitrc
{ echo "#! /bin/bash"

  echo "# set environment variables to new display and new cookie"
  echo "export DISPLAY=$Newdisplay"
  echo "export XAUTHORITY=$Xclientcookie"

  echo "# same keyboard layout as on host"
  echo "echo '$(setxkbmap -display $DISPLAY -print)' | xkbcomp - $Newdisplay"

  echo "# create new XAUTHORITY cookie file" 
  echo ":> $Xclientcookie"
  echo "xauth generate $Newdisplay . untrusted"
  echo "cp $Xclientcookie $Xservercookie"
  echo "# create prepared cookie with localhost identification disabled by ffff,"
  echo "# needed if X socket is shared instead connecting over tcp. ffff means 'familiy wild'"
  echo 'Cookie=$(xauth nlist '"$Newdisplay | sed -e 's/^..../ffff/')" 
  echo 'echo $Cookie | xauth -f '$Xclientcookie' nmerge -'

  echo "# run window manager in Xephyr"
  echo $Windowmanager' & Windowmanagerpid=$!'

  echo "# show docker log"
  echo 'tail --retry -n +1 -F '$Dockerlogfile' 2>/dev/null & Tailpid=$!'

  echo "# prompt for password"
  echo "xterm -title x11docker_example -e '/bin/bash $Xtermrc'"

  echo "# wait for docker to finish"
  echo 'Dockerpid=$(cat '$Dockerpidfile') && {'
  echo '  while [ -n "$(pgrep docker | grep $Dockerpid)" ] ; do'
  echo '    sleep 1'
  echo '  done }'

  [ "$Windowmanager" = ":" ] || echo 'kill $Windowmanagerpid'
  echo 'kill $Tailpid'
} > $Xinitrc


# create xtermrc for a password prompt
{ echo "#! /bin/bash"
  echo "echo 'x11docker_example will start docker on display $Newdisplay with command:'"
  echo "echo $Getroot '$Dockercommand'"
  echo "echo 'Please type in your password to run docker:'"
  echo "$Getroot 'nohup $Dockercommand 2>&1 1>$Dockerlogfile & echo "'$!'" > $Dockerpidfile'"
} > $Xtermrc


xinit  $Xinitrc -- $Xcommand
rm -Rf $Cachefolder

#9


9  

This is not lightweight but is a nice solution that gives docker feature parity with full desktop virtualization. Both Xfce4 or IceWM for Ubuntu and CentOS work, and the noVNC option makes for an easy access through a browser.

这不是轻量级的,但是是一个很好的解决方案,使docker具有与完全桌面虚拟化相同的特性。Xfce4或IceWM都适用于Ubuntu和CentOS,而noVNC选项则可以通过浏览器轻松访问。

https://github.com/ConSol/docker-headless-vnc-container

https://github.com/ConSol/docker-headless-vnc-container

It runs noVNC as well as tigerVNC's vncserver. Then it calls startx for given Window Manager. In addition, libnss_wrapper.so is used to emulate password management for the users.

它运行noVNC和tigerVNC的vncserver。然后它调用startx给给定的窗口管理器。此外,libnss_wrapper。因此,用于模拟用户的密码管理。

#10


6  

There is another solution by lord.garbage to run GUI apps in a container without using VNC, SSH and X11 forwarding. It is mentioned here too.

这是上帝的另一个解决办法。在不使用VNC、SSH和X11转发的情况下,垃圾在一个容器中运行GUI应用程序。这里也提到了。

#11


6  

If you want to run a GUI application headless, then read here. What you have to do is to create a virtual monitor with xvfb or other similar software. This is very helpful if you want to run Selenium tests for example with browsers.

如果您想要运行GUI应用程序headless,那么请在这里阅读。您需要做的是用xvfb或其他类似的软件创建一个虚拟监视器。如果您想在浏览器中运行Selenium测试,这将非常有用。

Something not mentioned anywhere is that some software actually themselves use sand-boxing with Linux containers. So for example Chrome will never run normally if you don't use the appropriate flag --privileged when running the container.

在任何地方都没有提到的一点是,有些软件实际上是用Linux容器来使用沙箱。例如,如果你在运行容器时不使用适当的标志,Chrome将永远不会正常运行。

#12


6  

The solution given at http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/ does seem to be an easy way of starting GUI applications from inside the containers ( I tried for firefox over ubuntu 14.04) but I found that a small additional change is required to the solution posted by the author.

在http://fabiorehm.com/blog/2014/09/09/11/runing - GUI -apps- docker/中给出的解决方案似乎是一种从容器内部启动GUI应用程序的简单方法(我在ubuntu 14.04上试用了firefox),但我发现,作者发布的解决方案需要额外的修改。

Specifically, for running the container, the author has mentioned:

具体来说,对于运行容器,作者提到:

    docker run -ti --rm \
    -e DISPLAY=$DISPLAY \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    firefox

But I found that (based on a particular comment on the same site) that two additional options

但我发现(基于同一网站上的一个特别评论),另外两个选项。

    -v $HOME/.Xauthority:$HOME/.Xauthority

and

    -net=host 

need to be specified while running the container for firefox to work properly:

在运行firefox的容器时需要指定正确的工作:

    docker run -ti --rm \
    -e DISPLAY=$DISPLAY \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -v $HOME/.Xauthority:$HOME/.Xauthority \
    -net=host \
    firefox

I have created a docker image with the information on that page and these additional findings: https://hub.docker.com/r/amanral/ubuntu-firefox/

我已经创建了一个docker映像,其中包含了该页面上的信息以及这些额外的发现:https://hub.docker.com/r/amanral/ubuntu-firefox/。

#13


4  

Based on Jürgen Weigert's answer, I have some improvement:

根据Jurgen Weigert的回答,我有一些改进:

docker build -t xeyes - << __EOF__
FROM debian
RUN apt-get update
RUN apt-get install -qqy x11-apps
ENV DISPLAY :0
CMD xeyes
__EOF__
XSOCK=/tmp/.X11-unix
XAUTH_DIR=/tmp/.docker.xauth
XAUTH=$XAUTH_DIR/.xauth
mkdir -p $XAUTH_DIR && touch $XAUTH
xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
docker run -ti -v $XSOCK:$XSOCK -v $XAUTH_DIR:$XAUTH_DIR -e XAUTHORITY=$XAUTH xeyes

The only difference is that it creates a directory $XAUTH_DIR which is used to place $XAUTH file and mount $XAUTH_DIR directory instead of $XAUTH file into docker container.

惟一的区别是,它创建了一个目录$XAUTH_DIR,用于将$XAUTH文件和mount $XAUTH_DIR目录放在docker容器中,而不是$XAUTH文件。

The benefit of this method is that you can write a command in /etc/rc.local which is to create a empty folder named $XAUTH_DIR in /tmp and change its mode to 777.

这种方法的好处是您可以在/etc/rc中编写一个命令。本地创建一个名为$XAUTH_DIR的空文件夹,并将其模式更改为777。

tr '\n' '\000' < /etc/rc.local | sudo tee /etc/rc.local >/dev/null
sudo sed -i 's|\x00XAUTH_DIR=.*\x00\x00|\x00|' /etc/rc.local >/dev/null
tr '\000' '\n' < /etc/rc.local | sudo tee /etc/rc.local >/dev/null
sudo sed -i 's|^exit 0.*$|XAUTH_DIR=/tmp/.docker.xauth; rm -rf $XAUTH_DIR; install -m 777 -d $XAUTH_DIR\n\nexit 0|' /etc/rc.local

When system restart, before user login, docker will mount the $XAUTH_DIR directory automatically if container's restart policy is "always". After user login, you can write a command in ~/.profile which is to create $XAUTH file, then the container will automatically use this $XAUTH file.

当系统重新启动时,在用户登录之前,docker将自动挂载$XAUTH_DIR目录,如果容器的重启策略是“always”。在用户登录之后,您可以在~/中编写一个命令。创建$XAUTH文件的概要文件,然后容器将自动使用这个$XAUTH文件。

tr '\n' '\000' < ~/.profile | sudo tee ~/.profile >/dev/null
sed -i 's|\x00XAUTH_DIR=.*-\x00|\x00|' ~/.profile
tr '\000' '\n' < ~/.profile | sudo tee ~/.profile >/dev/null
echo "XAUTH_DIR=/tmp/.docker.xauth; XAUTH=\$XAUTH_DIR/.xauth; touch \$XAUTH; xauth nlist \$DISPLAY | sed -e 's/^..../ffff/' | xauth -f \$XAUTH nmerge -" >> ~/.profile

Afterall, the container will automatically get the Xauthority file every time the system restart and user login.

毕竟,当系统重新启动和用户登录时,容器将自动获得Xauthority文件。

#14


3  

For OpenGL rendering with the Nvidia driver, use the following image:

对于OpenGL渲染与Nvidia驱动,使用以下图像:

https://github.com/thewtex/docker-opengl-nvidia

https://github.com/thewtex/docker-opengl-nvidia

For other OpenGL implementations, make sure the image has the same implementation as the host.

对于其他OpenGL实现,确保映像与主机具有相同的实现。

#15


3  

I'm late to the party, but for Mac users who don't want to go down the XQuartz path, here is a working example that builds a Fedora Image, with a Desktop Environment (xfce) using Xvfb and VNC. It's simple, and works:

我已经迟到了,但是对于那些不想走XQuartz路径的Mac用户来说,这里有一个使用Xvfb和VNC的桌面环境(xfce)构建Fedora映像的工作示例。很简单,工作原理:

On a Mac, you can just access it using the Screen Sharing (default) application, connecting to localhost:5901.

在Mac上,您可以使用屏幕共享(默认)应用程序访问它,连接到localhost:5901。

Dockerfile:

Dockerfile:

FROM fedora

USER root

# Set root password, so I know it for the future
RUN echo "root:password123" | chpasswd

# Install Java, Open SSL, etc.
RUN dnf update -y --setopt=deltarpm=false  \
 && dnf install -y --setopt=deltarpm=false \
                openssl.x86_64             \
                java-1.8.0-openjdk.x86_64  \
                xorg-x11-server-Xvfb       \
                x11vnc                     \
                firefox                    \
                @xfce-desktop-environment  \
 && dnf clean all

# Create developer user (password: password123, uid: 11111)
RUN useradd -u 11111 -g users -d /home/developer -s /bin/bash -p $(echo password123 | openssl passwd -1 -stdin) developer

# Copy startup script over to the developer home
COPY start-vnc.sh /home/developer/start-vnc.sh
RUN chmod 700 /home/developer/start-vnc.sh
RUN chown developer.users /home/developer/start-vnc.sh

# Expose VNC, SSH
EXPOSE 5901 22

# Set up VNC Password and DisplayEnvVar to point to Display1Screen0
USER developer
ENV  DISPLAY :1.0
RUN  mkdir ~/.x11vnc
RUN  x11vnc -storepasswd letmein ~/.x11vnc/passwd

WORKDIR /home/developer
CMD ["/home/developer/start-vnc.sh"]

start-vnc.sh

start-vnc.sh

#!/bin/sh

Xvfb :1 -screen 0 1024x768x24 &
sleep 5
x11vnc -noxdamage -many -display :1 -rfbport 5901 -rfbauth ~/.x11vnc/passwd -bg
sleep 2
xfce4-session &

bash
# while true; do sleep 1000; done

Check the linked readme for build and run commands if you want/need.

如果您想要/需要,请检查连接的readme以构建和运行命令。

#16


2  

You can allow the Docker user (here: root) to access the X11 display:

您可以允许Docker用户(这里:root)访问X11显示:

XSOCK=/tmp/.X11-unix
xhost +SI:localuser:root 
docker run -t -i --rm -v $XSOCK:$XSOCK:ro -e DISPLAY=unix$(DISPLAY) image 
xhost -SI:localuser:root

#1


182  

You can simply install a vncserver along with firefox :)

您可以简单地安装一个vncserver和firefox:)

I pushed an image vnc/firefox here: docker pull creack/firefox-vnc

我在这里推了一个图像vnc/firefox: docker拉creack/firefox-vnc。

The image has been made with this Dockerfile:

这张图片是用这个Dockerfile做的:

# Firefox over VNC
#
# VERSION               0.1
# DOCKER-VERSION        0.2

FROM    ubuntu:12.04
# Make sure the package repository is up to date
RUN     echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN     apt-get update

# Install vnc, xvfb in order to create a 'fake' display and firefox
RUN     apt-get install -y x11vnc xvfb firefox
RUN     mkdir ~/.vnc
# Setup a password
RUN     x11vnc -storepasswd 1234 ~/.vnc/passwd
# Autostart firefox (might not be the best way to do it, but it does the trick)
RUN     bash -c 'echo "firefox" >> /.bashrc'

This will create a docker container running vnc with the password 1234:

这将创建一个运行vnc的docker容器,密码为1234:

For docker version 1.3 or newer:

对于docker 1.3或更新版本:

docker run -p 5900 -e HOME=/ creack/firefox-vnc x11vnc -forever -usepw -create

docker运行- p5900 -e HOME=/ creack/firefox-vnc x11vnc -永远-usepw -create。

For docker before version 1.3:

在1.3版之前的docker:

docker run -p 5900 creack/firefox-vnc x11vnc -forever -usepw -create

docker运行- p5900 creack/firefox-vnc x11vnc -永远-usepw -create。

#2


150  

Xauthority becomes an issue with newer systems. I can either discard any protection with xhost + before running my docker containers, or I can pass in a well prepared Xauthority file. Typical Xauthority files are hostname specific. With docker, each container can have a different host name (set with docker run -h), but even setting the hostname of the container identical to the host system did not help in my case. xeyes (I like this example) simply would ignore the magic cookie and pass no credentials to the server. Hence we get an error message 'No protocol specified Cannot open display'

Xauthority成为新系统的一个问题。在运行docker容器之前,我可以使用xhost +来丢弃任何保护,或者我可以传入一个准备良好的Xauthority文件。典型的Xauthority文件是特定于主机名的。对于docker,每个容器都可以有一个不同的主机名(设置docker run -h),但即使设置与主机系统相同的容器的主机名也不能对我的情况有所帮助。xeyes(我喜欢这个例子)只是忽略了神奇的cookie,并没有向服务器传递任何凭据。因此,我们得到一个错误消息'没有指定的协议不能打开显示'

The Xauthority file can be written in a way so that the hostname does not matter. We need to set the Authentication Family to 'FamilyWild'. I am not sure, if xauth has a proper command line for this, so here is an example that combines xauth and sed to do that. We need to change the first 16 bits of the nlist output. The value of FamilyWild is 65535 or 0xffff.

Xauthority文件可以以某种方式写入,以便主机名不重要。我们需要将身份验证家族设置为“FamilyWild”。我不确定,如果xauth有一个合适的命令行,那么这里有一个结合xauth和sed的例子。我们需要更改nlist输出的前16位。FamilyWild的价值是65535或0xffff。

docker build -t xeyes - << __EOF__
FROM debian
RUN apt-get update
RUN apt-get install -qqy x11-apps
ENV DISPLAY :0
CMD xeyes
__EOF__
XSOCK=/tmp/.X11-unix
XAUTH=/tmp/.docker.xauth
xauth nlist :0 | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
docker run -ti -v $XSOCK:$XSOCK -v $XAUTH:$XAUTH -e XAUTHORITY=$XAUTH xeyes

#3


46  

With docker data volumes it's very easy to expose xorg's unix domain socket inside the container.

通过docker的数据量,很容易在容器内公开xorg的unix域套接字。

For example, with a Dockerfile like this:

例如,使用这样的Dockerfile:

FROM debian
RUN apt-get update
RUN apt-get install -qqy x11-apps
ENV DISPLAY :0
CMD xeyes

You could do the following:

你可以这样做:

$ docker build -t xeyes - < Dockerfile
$ XSOCK=/tmp/.X11-unix/X0
$ docker run -v $XSOCK:$XSOCK xeyes

This of course is essentially the same as X-forwarding. It grants the container full access to the xserver on the host, so it's only recommended if you trust what's inside.

当然这和x -转发是一样的。它允许容器在主机上完全访问xserver,所以只有在您信任内部的情况时才建议使用它。

Note: If you are concerned about security, a better solution would be to confine the app with mandatory- or role-based-access control. Docker achieves pretty good isolation, but it was designed with a different purpose in mind. Use AppArmor, SELinux, or GrSecurity, which were designed to address your concern.

注意:如果你担心安全问题,更好的解决方案是用强制性的或基于角色的访问控制来限制应用程序。Docker实现了非常好的隔离,但是它的设计目的是不同的。使用设备,SELinux或GrSecurity,这是用来解决您的问题的。

#4


46  

i just found this blog entry and want to share it here with you because i think it is the best way to do it and it is so easy.

我刚找到这个博客,想和你分享它,因为我认为这是最好的方法,而且很容易。

http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/

http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/

PROS:
+ no x server stuff in the docker container
+ no vnc client/server needed
+ no ssh with x forwarding
+ much smaller docker containers

优点:在docker容器中没有x服务器的东西+没有vnc客户端/服务器需要+没有x转发的ssh +更小的docker容器。

CONS:
- using x on the host (not meant for secure-sandboxing)

缺点:-在主机上使用x(不是为了安全沙箱)

in case the link will fail some day i have put the most important part here:
dockerfile:

万一链接失败,我把最重要的部分放在这里: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

build the image:

构建图像:

docker build -t firefox .

and the run command:

运行命令:

docker run -ti --rm \
   -e DISPLAY=$DISPLAY \
   -v /tmp/.X11-unix:/tmp/.X11-unix \
   firefox

of course you can also do this in the run command with sh -c "echo script-here"

当然你也可以在run命令中使用sh -c "echo script-here"

HINT: for audio take a look at: https://*.com/a/28985715/2835523

提示:对于音频,请查看:https://*.com/a/28985715/2835523。

#5


23  

You can also use subuser: https://github.com/timthelion/subuser

您也可以使用subuser: https://github.com/timthelion/subuser。

This allows you to package many gui apps in docker. Firefox and emacs have been tested so far. With firefox, webGL doesn't work though. Chromium doesn't work at all.

这允许您在docker中打包许多gui应用程序。Firefox和emacs已经进行了测试。而对于firefox, webGL并没有发挥作用。铬根本不起作用。

EDIT: Sound works!

编辑:良好的工作!

EDIT2: In the time since I first posted this, subuser has progressed greatly. I now have a website up subuser.org, and a new security model for connecting to X11 via XPRA bridging.

在我发布这篇文章的时候,subuser已经有了很大的进步。我现在有一个网站subuser.org,和一个新的安全模型连接到X11通过XPRA桥接。

#6


19  

OSX

Jürgen Weigert has the best answer that worked for me on Ubuntu, however on OSX, docker runs inside of VirtualBox and so the solution doesn't work without some more work.

Jurgen Weigert在Ubuntu上为我提供了最好的答案,但是在OSX上,docker在VirtualBox中运行,所以解决方案在没有更多工作的情况下无法工作。

I've got it working with these additional ingredients:

我用了这些额外的材料:

  1. Xquartz (OSX no longer ships with X11 server)
  2. Xquartz (OSX不再带有X11服务器)
  3. socket forwarding with socat (brew install socat)
  4. 用socat (brew安装socat)
  5. bash script to launch the container
  6. bash脚本启动容器。

I'd appreciate user comments to improve this answer for OSX, I'm not sure if socket forwarding for X is secure, but my intended use is for running the docker container locally only.

我希望用户评论能改进OSX的这个答案,我不确定是否为X的套接字转发是安全的,但是我的目的是只在本地运行docker容器。

Also, the script is a bit fragile in that it's not easy to get the IP address of the machine since it's on our local wireless so it's always some random IP.

另外,这个脚本有点脆弱,因为它是在我们本地的无线网络上,所以很难得到机器的IP地址,所以它总是一些随机的IP。

The BASH script I use to launch the container:

我用来启动容器的BASH脚本:

#!/usr/bin/env bash

CONTAINER=py3:2016-03-23-rc3
COMMAND=/bin/bash
NIC=en0

# Grab the ip address of this box
IPADDR=$(ifconfig $NIC | grep "inet " | awk '{print $2}')

DISP_NUM=$(jot -r 1 100 200)  # random display number between 100 and 200

PORT_NUM=$((6000 + DISP_NUM)) # so multiple instances of the container won't interfer with eachother

socat TCP-LISTEN:${PORT_NUM},reuseaddr,fork UNIX-CLIENT:\"$DISPLAY\" 2>&1 > /dev/null &

XSOCK=/tmp/.X11-unix
XAUTH=/tmp/.docker.xauth.$USER.$$
touch $XAUTH
xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -

docker run \
    -it \
    --rm \
    --user=$USER \
    --workdir="/Users/$USER" \
    -v "/Users/$USER:/home/$USER:rw" \
    -v $XSOCK:$XSOCK:rw \
    -v $XAUTH:$XAUTH:rw \
    -e DISPLAY=$IPADDR:$DISP_NUM \
    -e XAUTHORITY=$XAUTH \
    $CONTAINER \
    $COMMAND

rm -f $XAUTH
kill %1       # kill the socat job launched above

I'm able to get xeyes and matplotlib working with this approach.

我可以用这种方法得到xeyes和matplotlib。

Windows 7+

It's a bit easier on Windows 7+ with MobaXterm:

在Windows 7+中使用MobaXterm比较容易:

  1. Install MobaXterm for windows
  2. 为windows安装MobaXterm
  3. Start MobaXterm
  4. 开始MobaXterm
  5. Configure X server: Settings -> X11 (tab) -> set X11 Remote Access to full
  6. 配置X服务器:设置-> X11 (tab) ->设置X11远程访问。
  7. Use this BASH script to launch the container
  8. 使用此BASH脚本启动容器。

run_docker.bash:

run_docker.bash:

#!/usr/bin/env bash

CONTAINER=py3:2016-03-23-rc3
COMMAND=/bin/bash
DISPLAY="$(hostname):0"
USER=$(whoami)

docker run \
    -it \
    --rm \
    --user=$USER \
    --workdir="/home/$USER" \
    -v "/c/Users/$USER:/home/$USER:rw" \
    -e DISPLAY \
    $CONTAINER \
    $COMMAND

你能在docker容器中运行GUI应用程序吗?

#7


17  

Here's a lightweight solution that avoids having to install any X server, vnc server or sshd daemon on the container. What it gains in simplicity it loses in security and isolation.

这里有一个轻量级的解决方案,可以避免在容器上安装任何X服务器、vnc服务器或sshd守护进程。它在简单中获得的好处在安全和隔离中失去了。

It assumes that you connect to the host machine using ssh with X11 forwarding.

它假定您使用ssh与X11转发连接到主机。

In the sshd configuration of the host, add the line

在主机的sshd配置中,添加一行。

X11UseLocalhost no

So that the forwarded X server port on the host is opened on all interfaces (not just lo) and in particular on the Docker virtual interface, docker0.

因此,主机上转发的X服务器端口在所有接口上都打开(不只是lo),尤其是在Docker虚拟接口上,docker0。

The container, when run, needs access to the .Xauthority file so that it can connect to the server. In order to do that, we define a read-only volume pointing to the home directory on the host (maybe not a wise idea!) and also set the XAUTHORITY variable accordingly.

在运行时,容器需要访问. xauthority文件,以便它可以连接到服务器。为了做到这一点,我们定义一个只读的量,指向主机上的主目录(可能不是一个明智的主意!),并相应地设置XAUTHORITY变量。

docker run -v $HOME:/hosthome:ro -e XAUTHORITY=/hosthome/.Xauthority

That is not enough, we also have to pass the DISPLAY variable from the host, but substituting the hostname by the ip:

这还不够,我们还必须从主机传递显示变量,但要用ip替换主机名:

-e DISPLAY=$(echo $DISPLAY | sed "s/^.*:/$(hostname -i):/")

We can define an alias:

我们可以定义一个别名:

 alias dockerX11run='docker run -v $HOME:/hosthome:ro -e XAUTHORITY=/hosthome/.Xauthority -e DISPLAY=$(echo $DISPLAY | sed "s/^.*:/$(hostname -i):/")'

And test it like this:

然后像这样测试:

dockerX11run centos xeyes

#8


10  

Sharing host display :0, as stated in some other answers, has two drawbacks:

共享主机显示:0,如其他答案所述,有两个缺点:

  • It breaks container isolation due to some X security leaks. For example, keylogging with xev or xinput is possible.
  • 由于某些X安全漏洞,它打破了容器隔离。例如,使用xev或xinput进行键盘记录是可能的。
  • Applications can have rendering glitches and bad RAM access errors due to missing shared memory for X extension MIT-SHM.
  • 由于对X扩展mitshm缺少共享内存,应用程序可能会出现故障和错误的RAM访问错误。

To circumvent X security leaks and to avoid MIT-SHM issue, I have published x11docker on github. The main idea is to run a second X server with its own authentication cookies and with MIT-SHM disabled. docker containers get access to the new X server and are segregated from host display :0. There are no X dependencies inside the image as X / Xephyr is provided by host.

为了规避X安全漏洞,并避免MIT-SHM问题,我在github上发布了x11docker。主要的想法是使用自己的身份验证cookie运行第二个X服务器,并禁用mitshm。docker容器可以访问新的X服务器,并与主机显示隔离:0。当X / Xephyr由主机提供时,图像中没有X依赖项。

Below an example script to run a docker image in Xephyr. It expects some arguments, first a host window manager to run in Xephyr, second a docker image, optionally third an image command to be executed. To run a desktop environment in docker, use ":" instead of a host window manager. On systems without a root password, change variable $Getroot

下面是在Xephyr中运行docker映像的示例脚本。它需要一些参数,首先是一个主机窗口管理器,它运行在Xephyr中,第二个是docker镜像,可选第三个要执行的图像命令。要在docker中运行桌面环境,请使用“:”而不是主机窗口管理器。在没有根密码的系统上,更改变量$Getroot。

Xephyr is started using xinit. A custom xinitrc is created to create a cookie, to set keyboard layout, to run window manager, and to run xterm with xtermrc to prompt for password to run docker.

Xephyr开始使用xinit。创建一个自定义xinitrc来创建一个cookie,设置键盘布局,运行窗口管理器,并使用xtermrc运行xterm,以提示密码运行docker。

Closing Xephyr window terminates docker container applications. Terminating the dockered applications closes Xephyr window.

关闭Xephyr窗口会终止docker容器应用程序。终止docker应用程序关闭Xephyr窗口。

Annotations:

注释:

  • The MIT-SHM problem also can be avoided with docker option --ipc=host, but this breaks down container isolation and is discouraged.
  • 也可以使用docker选项——ipc=主机来避免MIT-SHM问题,但是这打破了容器的隔离,并且是不鼓励的。
  • The cookie has to be changed to "familiy wild" as described by @Jürgen Weigert if shared X socket is used. With X over tcp, this is not needed.
  • 如果使用共享的X套接字,则必须将cookie更改为“familiy wild”,如@Jurgen Weigert所述。对于X / tcp,这是不需要的。
  • similar solutions are possible with Xpra, Xorg and Xvnc
  • Xpra、Xorg和Xvnc也有类似的解决方案。
  • For X over tcp, find out docker daemon ip (mostly 172.17.42.1), share DISPLAY=172.17.42.1:1, create cookie for it, don't share NewXsocket and don't use X/Xephyr option -nolisten tcp. Using X over tcp, MIT-SHM is disabled automatically.
  • 对于X/ tcp,查找docker守护进程ip(主要是172.17.42.1),共享显示=172.17.42.1:1,为它创建cookie,不要共享NewXsocket,也不要使用X/Xephyr选项-nolisten tcp。在tcp上使用X, MIT-SHM被自动禁用。

Examples:

例子:

  • x11docker_example "openbox --sm-disable" x11docker/lxde pcmanfm
  • x11docker_example“openbox—sm-disable”x11docker/lxde pcmanfm。
  • x11docker_example : x11docker/lxde
  • x11docker_example:x11docker /插件

x11docker_example script:

x11docker_example脚本:

#! /bin/bash
# x11docker_example : Example script to run docker GUI applications in Xephyr.
#                     Look at x11docker on github: https://github.com/mviereck/x11docker
#
# Usage:
#   x11docker_example WINDOWMANAGER DOCKERIMAGE [IMAGECOMMAND [ARGS]]
#
# WINDOWMANAGER     host window manager for use with single GUI applications.
#                   To run a desktop environment in docker, use ":"
# DOCKERIMAGE       docker image containing GUI applications or a desktop
# IMAGECOMMAND      command to run in image
#
Windowmanager="$1" && shift
Dockerimage="$*"

# command to get root permissions to run docker
Getroot="su -c"
# Getroot="sudo su -c"      # Use this on systems without a root password like Ubuntu or Sparky

# define new display and its X socket.
Newdisplay=:1
# To make sure $Newdisplay is not already in use, check /tmp/.Xn-lock
[ -e "/tmp/.X1-lock" ] && echo "Error: Display :1 is already in use" >&2 && exit 1
NewXsocket=/tmp/.X11-unix/X1


# cache folder and files
Cachefolder=/tmp/x11docker_example
mkdir -p $Cachefolder
Xclientcookie=$Cachefolder/Xcookie.client
Xservercookie=$Cachefolder/Xcookie.server
Xtermrc=$Cachefolder/xtermrc
Xinitrc=$Cachefolder/xinitrc
Dockerpidfile=$Cachefolder/docker.pid
Dockerlogfile=$Cachefolder/docker.log


# command to run docker
# --rm                           created container will be discarded.
# -e DISPLAY=$Newdisplay         set environment variable to new display
# -e XAUTHORITY=/Xcookie         set environment variable XAUTHORITY to provided cookie
# -v $Xclientcookie:/Xcookie:ro  provide cookie file to container
# -v $NewXsocket:$NewXsocket:ro  Share new X socket of Xephyr
Dockercommand="docker run --rm -e DISPLAY=$Newdisplay -e XAUTHORITY=/Xcookie -v $Xclientcookie:/Xcookie:ro -v $NewXsocket:$NewXsocket:ro $Dockerimage"  


# command to run X/Xephyr
# /usr/bin/Xephyr                an absolute path to X server executable must be given
# $Newdisplay                    first argument has to be new display
# -auth $Xservercookie           path to cookie file for X server. Must be different from cookie file of client, not sure why
# -nolisten tcp                  disable tcp connections for security reasons
# -extension MIT-SHM             disable MIT-SHM to avoid rendering glitches and bad RAM access (+ instead of - enables it)
# -retro                         nice retro look
Xcommand="/usr/bin/Xephyr $Newdisplay -auth $Xservercookie -nolisten tcp -extension MIT-SHM -retro"


# create xinitrc
{ echo "#! /bin/bash"

  echo "# set environment variables to new display and new cookie"
  echo "export DISPLAY=$Newdisplay"
  echo "export XAUTHORITY=$Xclientcookie"

  echo "# same keyboard layout as on host"
  echo "echo '$(setxkbmap -display $DISPLAY -print)' | xkbcomp - $Newdisplay"

  echo "# create new XAUTHORITY cookie file" 
  echo ":> $Xclientcookie"
  echo "xauth generate $Newdisplay . untrusted"
  echo "cp $Xclientcookie $Xservercookie"
  echo "# create prepared cookie with localhost identification disabled by ffff,"
  echo "# needed if X socket is shared instead connecting over tcp. ffff means 'familiy wild'"
  echo 'Cookie=$(xauth nlist '"$Newdisplay | sed -e 's/^..../ffff/')" 
  echo 'echo $Cookie | xauth -f '$Xclientcookie' nmerge -'

  echo "# run window manager in Xephyr"
  echo $Windowmanager' & Windowmanagerpid=$!'

  echo "# show docker log"
  echo 'tail --retry -n +1 -F '$Dockerlogfile' 2>/dev/null & Tailpid=$!'

  echo "# prompt for password"
  echo "xterm -title x11docker_example -e '/bin/bash $Xtermrc'"

  echo "# wait for docker to finish"
  echo 'Dockerpid=$(cat '$Dockerpidfile') && {'
  echo '  while [ -n "$(pgrep docker | grep $Dockerpid)" ] ; do'
  echo '    sleep 1'
  echo '  done }'

  [ "$Windowmanager" = ":" ] || echo 'kill $Windowmanagerpid'
  echo 'kill $Tailpid'
} > $Xinitrc


# create xtermrc for a password prompt
{ echo "#! /bin/bash"
  echo "echo 'x11docker_example will start docker on display $Newdisplay with command:'"
  echo "echo $Getroot '$Dockercommand'"
  echo "echo 'Please type in your password to run docker:'"
  echo "$Getroot 'nohup $Dockercommand 2>&1 1>$Dockerlogfile & echo "'$!'" > $Dockerpidfile'"
} > $Xtermrc


xinit  $Xinitrc -- $Xcommand
rm -Rf $Cachefolder

#9


9  

This is not lightweight but is a nice solution that gives docker feature parity with full desktop virtualization. Both Xfce4 or IceWM for Ubuntu and CentOS work, and the noVNC option makes for an easy access through a browser.

这不是轻量级的,但是是一个很好的解决方案,使docker具有与完全桌面虚拟化相同的特性。Xfce4或IceWM都适用于Ubuntu和CentOS,而noVNC选项则可以通过浏览器轻松访问。

https://github.com/ConSol/docker-headless-vnc-container

https://github.com/ConSol/docker-headless-vnc-container

It runs noVNC as well as tigerVNC's vncserver. Then it calls startx for given Window Manager. In addition, libnss_wrapper.so is used to emulate password management for the users.

它运行noVNC和tigerVNC的vncserver。然后它调用startx给给定的窗口管理器。此外,libnss_wrapper。因此,用于模拟用户的密码管理。

#10


6  

There is another solution by lord.garbage to run GUI apps in a container without using VNC, SSH and X11 forwarding. It is mentioned here too.

这是上帝的另一个解决办法。在不使用VNC、SSH和X11转发的情况下,垃圾在一个容器中运行GUI应用程序。这里也提到了。

#11


6  

If you want to run a GUI application headless, then read here. What you have to do is to create a virtual monitor with xvfb or other similar software. This is very helpful if you want to run Selenium tests for example with browsers.

如果您想要运行GUI应用程序headless,那么请在这里阅读。您需要做的是用xvfb或其他类似的软件创建一个虚拟监视器。如果您想在浏览器中运行Selenium测试,这将非常有用。

Something not mentioned anywhere is that some software actually themselves use sand-boxing with Linux containers. So for example Chrome will never run normally if you don't use the appropriate flag --privileged when running the container.

在任何地方都没有提到的一点是,有些软件实际上是用Linux容器来使用沙箱。例如,如果你在运行容器时不使用适当的标志,Chrome将永远不会正常运行。

#12


6  

The solution given at http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/ does seem to be an easy way of starting GUI applications from inside the containers ( I tried for firefox over ubuntu 14.04) but I found that a small additional change is required to the solution posted by the author.

在http://fabiorehm.com/blog/2014/09/09/11/runing - GUI -apps- docker/中给出的解决方案似乎是一种从容器内部启动GUI应用程序的简单方法(我在ubuntu 14.04上试用了firefox),但我发现,作者发布的解决方案需要额外的修改。

Specifically, for running the container, the author has mentioned:

具体来说,对于运行容器,作者提到:

    docker run -ti --rm \
    -e DISPLAY=$DISPLAY \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    firefox

But I found that (based on a particular comment on the same site) that two additional options

但我发现(基于同一网站上的一个特别评论),另外两个选项。

    -v $HOME/.Xauthority:$HOME/.Xauthority

and

    -net=host 

need to be specified while running the container for firefox to work properly:

在运行firefox的容器时需要指定正确的工作:

    docker run -ti --rm \
    -e DISPLAY=$DISPLAY \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -v $HOME/.Xauthority:$HOME/.Xauthority \
    -net=host \
    firefox

I have created a docker image with the information on that page and these additional findings: https://hub.docker.com/r/amanral/ubuntu-firefox/

我已经创建了一个docker映像,其中包含了该页面上的信息以及这些额外的发现:https://hub.docker.com/r/amanral/ubuntu-firefox/。

#13


4  

Based on Jürgen Weigert's answer, I have some improvement:

根据Jurgen Weigert的回答,我有一些改进:

docker build -t xeyes - << __EOF__
FROM debian
RUN apt-get update
RUN apt-get install -qqy x11-apps
ENV DISPLAY :0
CMD xeyes
__EOF__
XSOCK=/tmp/.X11-unix
XAUTH_DIR=/tmp/.docker.xauth
XAUTH=$XAUTH_DIR/.xauth
mkdir -p $XAUTH_DIR && touch $XAUTH
xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
docker run -ti -v $XSOCK:$XSOCK -v $XAUTH_DIR:$XAUTH_DIR -e XAUTHORITY=$XAUTH xeyes

The only difference is that it creates a directory $XAUTH_DIR which is used to place $XAUTH file and mount $XAUTH_DIR directory instead of $XAUTH file into docker container.

惟一的区别是,它创建了一个目录$XAUTH_DIR,用于将$XAUTH文件和mount $XAUTH_DIR目录放在docker容器中,而不是$XAUTH文件。

The benefit of this method is that you can write a command in /etc/rc.local which is to create a empty folder named $XAUTH_DIR in /tmp and change its mode to 777.

这种方法的好处是您可以在/etc/rc中编写一个命令。本地创建一个名为$XAUTH_DIR的空文件夹,并将其模式更改为777。

tr '\n' '\000' < /etc/rc.local | sudo tee /etc/rc.local >/dev/null
sudo sed -i 's|\x00XAUTH_DIR=.*\x00\x00|\x00|' /etc/rc.local >/dev/null
tr '\000' '\n' < /etc/rc.local | sudo tee /etc/rc.local >/dev/null
sudo sed -i 's|^exit 0.*$|XAUTH_DIR=/tmp/.docker.xauth; rm -rf $XAUTH_DIR; install -m 777 -d $XAUTH_DIR\n\nexit 0|' /etc/rc.local

When system restart, before user login, docker will mount the $XAUTH_DIR directory automatically if container's restart policy is "always". After user login, you can write a command in ~/.profile which is to create $XAUTH file, then the container will automatically use this $XAUTH file.

当系统重新启动时,在用户登录之前,docker将自动挂载$XAUTH_DIR目录,如果容器的重启策略是“always”。在用户登录之后,您可以在~/中编写一个命令。创建$XAUTH文件的概要文件,然后容器将自动使用这个$XAUTH文件。

tr '\n' '\000' < ~/.profile | sudo tee ~/.profile >/dev/null
sed -i 's|\x00XAUTH_DIR=.*-\x00|\x00|' ~/.profile
tr '\000' '\n' < ~/.profile | sudo tee ~/.profile >/dev/null
echo "XAUTH_DIR=/tmp/.docker.xauth; XAUTH=\$XAUTH_DIR/.xauth; touch \$XAUTH; xauth nlist \$DISPLAY | sed -e 's/^..../ffff/' | xauth -f \$XAUTH nmerge -" >> ~/.profile

Afterall, the container will automatically get the Xauthority file every time the system restart and user login.

毕竟,当系统重新启动和用户登录时,容器将自动获得Xauthority文件。

#14


3  

For OpenGL rendering with the Nvidia driver, use the following image:

对于OpenGL渲染与Nvidia驱动,使用以下图像:

https://github.com/thewtex/docker-opengl-nvidia

https://github.com/thewtex/docker-opengl-nvidia

For other OpenGL implementations, make sure the image has the same implementation as the host.

对于其他OpenGL实现,确保映像与主机具有相同的实现。

#15


3  

I'm late to the party, but for Mac users who don't want to go down the XQuartz path, here is a working example that builds a Fedora Image, with a Desktop Environment (xfce) using Xvfb and VNC. It's simple, and works:

我已经迟到了,但是对于那些不想走XQuartz路径的Mac用户来说,这里有一个使用Xvfb和VNC的桌面环境(xfce)构建Fedora映像的工作示例。很简单,工作原理:

On a Mac, you can just access it using the Screen Sharing (default) application, connecting to localhost:5901.

在Mac上,您可以使用屏幕共享(默认)应用程序访问它,连接到localhost:5901。

Dockerfile:

Dockerfile:

FROM fedora

USER root

# Set root password, so I know it for the future
RUN echo "root:password123" | chpasswd

# Install Java, Open SSL, etc.
RUN dnf update -y --setopt=deltarpm=false  \
 && dnf install -y --setopt=deltarpm=false \
                openssl.x86_64             \
                java-1.8.0-openjdk.x86_64  \
                xorg-x11-server-Xvfb       \
                x11vnc                     \
                firefox                    \
                @xfce-desktop-environment  \
 && dnf clean all

# Create developer user (password: password123, uid: 11111)
RUN useradd -u 11111 -g users -d /home/developer -s /bin/bash -p $(echo password123 | openssl passwd -1 -stdin) developer

# Copy startup script over to the developer home
COPY start-vnc.sh /home/developer/start-vnc.sh
RUN chmod 700 /home/developer/start-vnc.sh
RUN chown developer.users /home/developer/start-vnc.sh

# Expose VNC, SSH
EXPOSE 5901 22

# Set up VNC Password and DisplayEnvVar to point to Display1Screen0
USER developer
ENV  DISPLAY :1.0
RUN  mkdir ~/.x11vnc
RUN  x11vnc -storepasswd letmein ~/.x11vnc/passwd

WORKDIR /home/developer
CMD ["/home/developer/start-vnc.sh"]

start-vnc.sh

start-vnc.sh

#!/bin/sh

Xvfb :1 -screen 0 1024x768x24 &
sleep 5
x11vnc -noxdamage -many -display :1 -rfbport 5901 -rfbauth ~/.x11vnc/passwd -bg
sleep 2
xfce4-session &

bash
# while true; do sleep 1000; done

Check the linked readme for build and run commands if you want/need.

如果您想要/需要,请检查连接的readme以构建和运行命令。

#16


2  

You can allow the Docker user (here: root) to access the X11 display:

您可以允许Docker用户(这里:root)访问X11显示:

XSOCK=/tmp/.X11-unix
xhost +SI:localuser:root 
docker run -t -i --rm -v $XSOCK:$XSOCK:ro -e DISPLAY=unix$(DISPLAY) image 
xhost -SI:localuser:root