你可以在Docker容器中运行GUI应用程序吗?

Wil*_*ill 380 x11 vnc sandbox docker

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

是否有任何图像设置vncserver或某些东西,以便你可以 - 例如 - 在Firefox周围添加一个额外的speedbump沙箱?

cre*_*ack 229

你可以简单地安装一个vncserver和Firefox :)

我在这里推了一个图片,vnc/firefox: docker pull creack/firefox-vnc

该镜像是使用此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'
Run Code Online (Sandbox Code Playgroud)

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

对于Docker 1.3或更高版本:

docker run -p 5900:5900 -e HOME=/ creack/firefox-vnc x11vnc -forever -usepw -create
Run Code Online (Sandbox Code Playgroud)

对于版本1.3之前的Docker:

docker run -p 5900 -e HOME=/ creack/firefox-vnc x11vnc -forever -usepw -create
Run Code Online (Sandbox Code Playgroud)

  • 首先,你需要检查分配的端口(通过`docker inspect <container id>`或者只是`docker ps`,然后你用你刚找到的端口连接到主机的ip. (17认同)
  • creackfirefox-vnc映像失败并显示错误:输入VNC密码:stty:标准输入:设备fgets的不适当的ioctl:没有这样的文件或目录stty:标准输入:设备x11vnc -usepw的不适当的ioctl:找不到要使用的密码. (9认同)
  • 没有用户名,密码在答案中清楚地显示,任何vnc客户端都会这样做.就我而言,我喜欢原生的osx.(从finder,按命令+ K并连接到vnc:// <docker ip>:<container exposed port>) (7认同)
  • 使用docker>使用Docker运行GUI应用程序http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/ (6认同)
  • 我如何使用VNC客户端远程查看?输入IP +端口似乎不起作用. (2认同)
  • 我似乎需要在 `docker run` 中使用 `-t` 来获得密码提示。我不确定为什么这里甚至需要密码。无论如何,请通过编辑原始说明而不是添加“编辑”部分来更新说明。 (2认同)

Jür*_*ert 190

Xauthority成为新系统的问题.在运行我的docker容器之前,我可以使用xhost +放弃任何保护,或者我可以传入一个准备充分的Xauthority文件.典型的Xauthority文件是特定于主机名的.使用docker,每个容器可以有不同的主机名(使用docker run -h设置),但即使将容器的主机名设置为与主机系统相同也无济于事.xeyes(我喜欢这个例子)只是忽略魔术cookie并且不向服务器传递凭证.因此,我们收到错误消息"未指定协议无法打开显示"

可以以某种方式编写Xauthority文件,以便主机名无关紧要.我们需要将Authentication Family设置为'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
Run Code Online (Sandbox Code Playgroud)

  • @Dirk:您可能想用`$ DISPLAY`替换`:0`.这意味着`xauth nlist $ DISPLAY | ...`和`docker run -ti -e DISPLAY = $ DISPLAY ...`.通常X DISPLAY是`:0`,但并不总是(尤其是如果你通过ssh -X连接的话). (13认同)
  • 只需注意,`-v $ XSOCK:$ XSOCK -v $ XAUTH:$ XAUTH`可以缩短为`-v $ XSOCK -v $ XAUTH` (7认同)
  • 仅适用于登陆这里的人:@PiotrAleksanderChmielowski 评论对我不起作用,我还必须添加 `--net=host` (4认同)
  • 在Ubuntu 16.04上,xauth创建了具有`600`权限的`/ tmp/.docker.xauth`文件.这导致docker容器内的xauth无法读取文件.您可以通过在docker容器中运行`xauth list`来进行验证.我在`xauth nlist:0 |之后添加了`chmod 755 $ XAUTH` ...``命令来解决这个问题. (4认同)
  • 以下内容对我有用(特别是添加 `-e DISPLAY=$DISPLAY`),将最后四行替换为:`xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | sed -e 's/^..../ffff/' | xauth -f /tmp/.docker.xauth nmerge - &amp;&amp; docker run -it -v /tmp/.X11-unix:/tmp/.X11-unix -v /tmp/.docker.xauth:/tmp/.docker。 xauth -e XAUTHORITY=/tmp/.docker.xauth -e DISPLAY=$DISPLAY xeyes` (4认同)
  • @PiotrAleksanderChmielowski对我不起作用,Docker版本1.12.0,构建8eab29e (2认同)
  • @Abai如果444或644足够,为什么要使用755? (2认同)

A. *_*xxx 63

我刚刚找到了这篇博客文章,想在这里与大家分享,因为我觉得这是最好的方式,而且很容易.

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

PROS:
+在docker容器中没有x服务器东西
+没有vnc客户端/服务器需要
+没有带有x转发的ssh
+更小的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
Run Code Online (Sandbox Code Playgroud)

建立图像:

docker build -t firefox .
Run Code Online (Sandbox Code Playgroud)

和运行命令:

docker run -ti --rm \
   -e DISPLAY=$DISPLAY \
   -v /tmp/.X11-unix:/tmp/.X11-unix \
   firefox
Run Code Online (Sandbox Code Playgroud)

当然你也可以在run命令中执行此操作 sh -c "echo script-here"

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

  • 作为这里的大多数答案,这仅适用于我认为的Unix-直到Windows支持X服务器窗口系统。 (3认同)
  • 我认为您还需要在 Dockerfile 中安装 `apt-get -y install sudo` 来创建 `/etc/sudoers.d` 文件夹。 (2认同)
  • 可能还需要允许使用“$ xhost +”从任何主机连接到 X (2认同)

Ary*_*rog 49

使用docker数据卷,可以很容易地在容器中公开xorg的unix域套接字.

例如,使用这样的Dockerfile:

FROM debian
RUN apt-get update
RUN apt-get install -qqy x11-apps
ENV DISPLAY :0
CMD xeyes
Run Code Online (Sandbox Code Playgroud)

您可以执行以下操作:

$ docker build -t xeyes - < Dockerfile
$ XSOCK=/tmp/.X11-unix/X0
$ docker run -v $XSOCK:$XSOCK xeyes
Run Code Online (Sandbox Code Playgroud)

这当然与X-forwarding基本相同.它授予容器对主机上xserver的完全访问权限,因此只有在您信任其中的内容时才建议使用它.

注意:如果您担心安全性,更好的解决方案是将应用程序限制为基于强制基于角色的访问控制.Docker实现了相当好的隔离,但它的设计考虑了不同的目的.使用AppArmor,SELinuxGrSecurity,旨在解决您的问题.

  • 您还需要允许使用xhost等工具从其他主机访问X Server.要完全打开它,请在主机上使用`xhost +`. (5认同)
  • 我使用```xhost + si:localuser:$ USER```来授权用户启动容器. (5认同)
  • 对于我来说,这对我来说相当不错,Ubuntu 14.04笔记本电脑早先有docker 1.5; 但现在在Ubuntu 15.04,docker 1.6.2上失败了,错误是"无法打开显示:: 0".有任何想法吗? (4认同)
  • @Tully只需要`xhost + local`是必要的.最好在容器中使用`〜/ .Xauthority`文件,因此它可以自我验证. (3认同)
  • 你有没有设法让它在Mac上工作(使用boot2docker)? (3认同)
  • @AryehLeibTaurog我认为你的命令`xhost + local:`中缺少尾随冒号.没有冒号,命令在Ubuntu 16.04上失败了 (3认同)

tim*_*ion 26

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

这允许您在docker中打包许多gui应用程序.到目前为止,Firefox和emacs已经过测试.使用firefox,webGL不起作用.铬根本不起作用.

编辑:声音工作!

编辑2:自从我第一次发布这篇文章以来,子用户已经取得了很大的进步.我现在有一个subuser.org网站,以及一个通过XPRA桥接连接到X11的新安全模型.

  • 请注意,子用户仍然是非常新的并且相对未经测试.如果您遇到任何问题,请提交错误报告! (3认同)

Nic*_*ick 24

OSX

JürgenWeigert在Ubuntu上有最适合我的答案,但是在OSX上,docker在VirtualBox内部运行,因此如果没有更多的工作,解决方案就无法工作.

我已经使用这些额外的成分:

  1. Xquartz(OSX不再附带X11服务器)
  2. 使用socat转发套接字(brew install socat)
  3. 用于启动容器的bash脚本

我会很感激用户的意见,以改善这个答案OSX,我不知道,如果插座转发的X是安全的,但我的用途是只在本地运行泊坞窗容器.

此外,该脚本有点脆弱,因为它不是很容易获得机器的IP地址,因为它在我们的本地无线上,因此它总是一些随机IP.

我用来启动容器的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
Run Code Online (Sandbox Code Playgroud)

我能够让xeyes和matplotlib使用这种方法.

Windows 7+

使用MobaXterm在Windows 7+上更容易一些:

  1. 安装MobaXterm for Windows
  2. 启动MobaXterm
  3. 配置X服务器:设置 - > X11(选项卡) - >将X11远程访问设置为完全
  4. 使用此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
Run Code Online (Sandbox Code Playgroud)

xeyes在PC上运行

  • 我收到有关未找到用户的错误,即“passwd 文件中没有匹配的条目”有任何线索吗? (2认同)

dan*_*iaz 18

这是一个轻量级的解决方案,可以避免在容器上安装任何X服务器,vnc服务器或sshd守护程序.它在简单性方面取得的成就在安全性和隔离性方面失败了.

它假定您使用连接到主机sshX11转发.

sshd主机配置中,添加该行

X11UseLocalhost no
Run Code Online (Sandbox Code Playgroud)

这样主机上转发的X服务器端口就可以在所有接口上打开(不仅仅是lo),特别是在Docker虚拟接口上docker0.

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

docker run -v $HOME:/hosthome:ro -e XAUTHORITY=/hosthome/.Xauthority
Run Code Online (Sandbox Code Playgroud)

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

-e DISPLAY=$(echo $DISPLAY | sed "s/^.*:/$(hostname -i):/")
Run Code Online (Sandbox Code Playgroud)

我们可以定义一个别名:

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

并像这样测试:

dockerX11run centos xeyes
Run Code Online (Sandbox Code Playgroud)

  • (这对于受信任的应用程序非常有用.但是,对于任何类型的沙盒,您都希望避免X-forwarding.) (2认同)
  • 您也可以使用附加选项`--net = host`作为`docker run`命令(找到[here](https://dzone.com/articles/docker-x11-client-),而不是更改`X11UseLocalhost`.经由-SSH)). (2认同)

mvi*_*eck 16

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

  • 由于一些X安全漏洞,它打破了容器隔离.例如,使用xevxinput可能进行键盘记录,以及使用主机应用程序进行远程控制xdotool.
  • 由于缺少X扩展MIT-SHM的共享内存,应用程序可能会出现渲染故障和错误的RAM访问错误.(也可以使用隔离降级选项进行修复--ipc=host).

下面是一个示例脚本,用于在Xephyr中运行一个解决此问题的docker镜像.

  • 它避免了X安全漏洞,因为docker应用程序在嵌套的X服务器中运行.
  • 禁用MIT-SHM以避免RAM访问失败.
  • 集装箱安全性得到改善--cap-drop ALL --security-opt no-new-privileges.容器用户也不是root用户.
  • 创建X cookie以限制对Xephyr显示的访问.

该脚本需要一些参数,首先是在Xephyr中运行的主机窗口管理器,第二个是docker镜像,可选地是第三个要执行的image命令.要在docker中运行桌面环境,请使用":"而不是主机窗口管理器.

关闭Xephyr窗口会终止docker容器应用程序.终止停靠应用程序将关闭Xephyr窗口.

例子:

  • xephyrdocker "openbox --sm-disable" x11docker/lxde pcmanfm
  • xephyrdocker : x11docker/lxde
  • xephyrdocker xfwm4 --device /dev/snd jess/nes /games/zelda.rom

xephyrdocker脚本:

#! /bin/bash
#
# Xephyrdocker:     Example script to run docker GUI applications in Xephyr.
#
# Usage:
#   Xephyrdocker WINDOWMANAGER DOCKERIMAGE [IMAGECOMMAND [ARGS]]
#
# WINDOWMANAGER     host window manager for use with single GUI applications.
#                   To run without window manager from host, use ":"
# DOCKERIMAGE       docker image containing GUI applications or a desktop
# IMAGECOMMAND      command to run in image
#
Windowmanager="$1" && shift
Dockerimage="$*"

# Container user
Useruid=$(id -u)
Usergid=$(id -g)
Username="$(id -un)"
[ "$Useruid" = "0" ] && Useruid=1000 && Usergid=1000 && Username="user$Useruid"

# Find free display number
for ((Newdisplaynumber=1 ; Newdisplaynumber <= 100 ; Newdisplaynumber++)) ; do
  [ -e /tmp/.X11-unix/X$Newdisplaynumber ] || break
done
Newxsocket=/tmp/.X11-unix/X$Newdisplaynumber

# cache folder and files
Cachefolder=/tmp/Xephyrdocker_X$Newdisplaynumber
[ -e "$Cachefolder" ] && rm -R "$Cachefolder"
mkdir -p $Cachefolder
Xclientcookie=$Cachefolder/Xcookie.client
Xservercookie=$Cachefolder/Xcookie.server
Xinitrc=$Cachefolder/xinitrc
Etcpasswd=$Cachefolder/passwd

# 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
# --user $Useruid:$Usergid           Security: avoid root in container
# -v $Etcpasswd:/etc/passwd:ro       /etc/passwd file with user entry
# --group-add audio                  Allow access to /dev/snd if shared with '--device /dev/snd' 
# --cap-drop ALL                     Security: disable needless capabilities
# --security-opt no-new-privileges   Security: forbid new privileges
Dockercommand="docker run --rm \
  -e DISPLAY=:$Newdisplaynumber \
  -e XAUTHORITY=/Xcookie \
  -v $Xclientcookie:/Xcookie:ro \
  -v $Newxsocket:$Newxsocket:rw \
  --user $Useruid:$Usergid \
  -v $Etcpasswd:/etc/passwd:ro \
  --group-add audio \
  --env HOME=/tmp \
  --cap-drop ALL \
  --security-opt no-new-privileges \
  $(command -v docker-init >/dev/null && echo --init) \
  $Dockerimage"

echo "docker command: 
$Dockercommand
"

# command to run Xorg or Xephyr
# /usr/bin/Xephyr                an absolute path to X server executable must be given for xinit
# :$Newdisplaynumber             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
# -extension MIT-SHM             disable MIT-SHM to avoid rendering glitches and bad RAM access (+ instead of - enables it)
# -nolisten tcp                  disable tcp connections for security reasons
# -retro                         nice retro look
Xcommand="/usr/bin/Xephyr :$Newdisplaynumber \
  -auth $Xservercookie \
  -extension MIT-SHM \
  -nolisten tcp \
  -screen 1000x750x24 \
  -retro"

echo "X server command:
$Xcommand
"

# create /etc/passwd with unprivileged user
echo "root:x:0:0:root:/root:/bin/sh" >$Etcpasswd
echo "$Username:x:$Useruid:$Usergid:$Username,,,:/tmp:/bin/sh" >> $Etcpasswd

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

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

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

  echo "# create new XAUTHORITY cookie file" 
  echo ":> $Xclientcookie"
  echo "xauth add :$Newdisplaynumber . $(mcookie)"
  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 '":$Newdisplaynumber | sed -e 's/^..../ffff/')" 
  echo 'echo $Cookie | xauth -f '$Xclientcookie' nmerge -'
  echo "cp $Xclientcookie $Xservercookie"
  echo "chmod 644 $Xclientcookie"

  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 "# run docker"
  echo "$Dockercommand"
} > $Xinitrc

xinit  $Xinitrc -- $Xcommand
rm -Rf $Cachefolder
Run Code Online (Sandbox Code Playgroud)

此脚本在x11docker wiki上维护.更高级的脚本是x11docker,它还支持GPU加速,网络摄像头和打印机共享等功能.


oro*_*hen 13

虽然JürgenWeigert的回答基本上涵盖了这个解决方案,但我一开始并不清楚那里描述的是什么.所以我会加上我的看法,万一其他人需要澄清.

首先,相关文档是X安全手册页.

许多在线消息来源建议只将X11 unix插座和~/.Xauthority文件安装到容器中.这些解决方案通常可以运气,但没有真正理解为什么,例如容器用户最终得到与用户相同的UID,因此不需要魔术密钥授权.

首先,Xauthority文件具有模式0600,因此容器用户将无法读取它,除非它具有相同的UID.

即使您将文件复制到容器中并更改所有权,仍然存在另一个问题.如果您xauth list使用相同的Xauthority文件在主机和容器上运行,您将看到列出的不同条目.这是因为xauth根据条目的运行位置过滤条目.

容器中的X客户端(即GUI应用程序)的行为与...相同xauth.换句话说,它没有看到在用户桌面上运行的X会话的神奇cookie.相反,它会看到您之前打开的所有"远程"X会话的条目(如下所述).

因此,您需要做的是添加一个新条目,其中包含容器的主机名和与主机cookie相同的十六进制密钥(即在桌面上运行的X会话),例如:

containerhostname/unix:0   MIT-MAGIC-COOKIE-1   <shared hex key>
Run Code Online (Sandbox Code Playgroud)

问题是必须xauth add在容器内添加cookie :

touch ~/.Xauthority
xauth add containerhostname/unix:0 . <shared hex key>
Run Code Online (Sandbox Code Playgroud)

否则,xauth以仅在容器外部看到的方式标记它.

该命令的格式为:

xauth add hostname/$DISPLAY protocol hexkey
Run Code Online (Sandbox Code Playgroud)

.代表MIT-MAGIC-COOKIE-1协议.

注意:无需复制或绑定.Xauthority到容器中.只需创建一个空白文件,如图所示,然后添加cookie.

JürgenWeigert的回答通过使用FamilyWild连接类型在主机上创建新的授权文件并将其复制到容器中来解决这个问题.请注意,它首先从~/.Xauthority使用中提取当前X会话的十六进制密钥xauth nlist.

所以必要的步骤是:

  • 为用户当前的X会话提取cookie的十六进制密钥.
  • 使用容器主机名和共享十六进制密钥在容器中创建新的Xauthority文件(或创建具有FamilyWild连接类型的cookie ).

我承认我不太了解它是如何FamilyWild工作的,xauth或者X或客户端如何从Xauthority文件中过滤条目,具体取决于它们的运行位置.欢迎提供更多相关信息.

如果要分发Docker应用程序,则需要一个启动脚本来运行容器,该容器获取用户X会话的十六进制密钥,并以前面解释的两种方式之一将其导入容器.

它还有助于理解授权过程的机制:

  • 在容器中运行的X客户端(即GUI应用程序)在Xauthority文件中查找与容器的主机名和值相匹配的cookie条目$DISPLAY.
  • 如果找到匹配的条目,则X客户端将其授权请求通过/tmp/.X11-unix容器中安装的目录中的相应套接字传递给X服务器.

注意: X11 Unix套接字仍然需要安装在容器中,否则容器将没有到X服务器的路由.出于安全原因,大多数发行版默认禁用对X服务器的TCP访问.

有关其他信息,为了更好地掌握X客户端/服务器关系的工作原理,查看SSH X转发的示例案例也很有帮助:

  • 在远程计算机上运行的SSH服务器模拟自己的X服务器.
  • 它将$DISPLAYSSH会话中的值设置为指向其自己的X服务器.
  • xauth用于为远程主机创建新cookie,并将其添加到Xauthority本地和远程用户的文件中.
  • 启动GUI应用程序时,它们会与SSH的模拟X服务器通信.
  • SSH服务器将此数据转发回本地桌面上的SSH客户端.
  • 本地SSH客户端将数据发送到桌面上运行的X服务器会话,就像SSH客户端实际上是X客户端(即GUI应用程序)一样.
  • X服务器使用接收的数据在桌面上呈现GUI.
  • 在此交换开始时,远程X客户端还使用刚刚创建的cookie发送授权请求.本地X服务器将其与本地副本进行比较.


das*_*esy 12

这不是轻量级的,但它是一个很好的解决方案,使docker功能与完整的桌面虚拟化相同.适用于Ubuntu和CentOS的Xfce4或IceWM都可以使用,该noVNC选项可以通过浏览器轻松访问.

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

noVNCtigerVNCvncserver 一样运行.然后它调用startx给定的Window Manager.此外,libnss_wrapper.so还用于模拟用户的密码管理.

  • @guilhermecgs是的,并且工作正常.从那以后我也尝试了docker中的`xpra`,这是无根X.`xpra`是最适合的IMO,比VNC更有效. (3认同)

Ans*_*ral 11

http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/上给出的解决方案似乎是一种从容器内部启动GUI应用程序的简单方法(我试过firefox通过ubuntu 14.04)但我发现作者发布的解决方案需要进行一些额外的更改.

具体来说,为了运行容器,作者提到:

    docker run -ti --rm \
    -e DISPLAY=$DISPLAY \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    firefox
Run Code Online (Sandbox Code Playgroud)

但我发现(基于对同一网站的特定评论)有两个额外的选项

    -v $HOME/.Xauthority:$HOME/.Xauthority
Run Code Online (Sandbox Code Playgroud)

    -net=host 
Run Code Online (Sandbox Code Playgroud)

需要在运行容器时指定firefox才能正常工作:

    docker run -ti --rm \
    -e DISPLAY=$DISPLAY \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -v $HOME/.Xauthority:$HOME/.Xauthority \
    -net=host \
    firefox
Run Code Online (Sandbox Code Playgroud)

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

  • 我发现你甚至根本没有通过`/ tmp/.X11-unix`套接字.它只适用于挂载`.Xauthority`和`--net = host`. (3认同)
  • 实际上,这是当今唯一可行的解​​决方案。使用`/ tmp / .X11-unix`作为卷不再有效,因为docker静默拒绝从粘性目录进行卷装载。 (2认同)

小智 9

其他解决方案应该有效,但这里是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
Run Code Online (Sandbox Code Playgroud)

在终端或脚本中:

  • xhost +si:localuser:$USER
  • xhost +local:docker
  • export DISPLAY=$DISPLAY
  • docker-compose up


niu*_*ech 7

lord.garbage还有另一种解决方案,可以在不使用VNC,SSH和X11转发的情况下在容器中运行GUI应用程序.这里也提到了.


Pit*_*kos 7

如果您想运行GUI应用程序无头,请阅读此处.您需要做的是使用xvfb其他类似软件创建虚拟监视器.如果您想要使用浏览器运行Selenium测试,这非常有用.

在任何地方都没有提到的是,有些软件实际上自己使用沙盒与Linux容器.因此,例如,如果--privileged在运行容器时未使用相应的标志,则Chrome将永远无法正常运行.


Vin*_*nce 5

我迟到了,但对于那些不想沿着XQuartz路径前进的Mac用户来说,这是一个用于构建Fedora映像的工作示例,使用Xvfb和使用桌面环境(xfce)VNC.它很简单,有效:

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

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

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

如果需要,请检查链接的自述文件以获取构建和运行命令.


all*_*lee 5

根据JürgenWeigert的回答,我有一些改进:

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

唯一的区别是它创建了一个目录$ XAUTH_DIR,它用于放置$ XAUTH文件并将$ XAUTH_DIR目录而不是$ XAUTH文件挂载到docker容器中.

这种方法的好处是你可以在/etc/rc.local中编写一个命令,即在/ tmp中创建一个名为$ 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
Run Code Online (Sandbox Code Playgroud)

系统重启时,在用户登录之前,如果容器的重启策略为"always",则docker将自动挂载$ XAUTH_DIR目录.用户登录后,您可以在〜/ .profile中编写一个命令来创建$ 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
Run Code Online (Sandbox Code Playgroud)

毕竟,每次系统重启和用户登录时,容器都会自动获取Xauthority文件.


tsv*_*iko 5

opencv我设法使用docker以下步骤从 USB 摄像头运行视频流:

  1. 让docker访问X服务器

    xhost +local:docker
    
    Run Code Online (Sandbox Code Playgroud)
  2. 创建 X11 Unix 套接字和 X 身份验证文件

    XSOCK=/tmp/.X11-unix
    XAUTH=/tmp/.docker.xauth
    
    Run Code Online (Sandbox Code Playgroud)
  3. 添加适当的权限

    xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
    
    Run Code Online (Sandbox Code Playgroud)
  4. 将Qt渲染速度设置为“native”,这样它就不会绕过X11渲染引擎

    export QT_GRAPHICSSYSTEM=native
    
    Run Code Online (Sandbox Code Playgroud)
  5. 告诉 Qt 不要使用 MIT-SHM(共享内存) - 这样它在安全方面也应该更安全

    export QT_X11_NO_MITSHM=1
    
    Run Code Online (Sandbox Code Playgroud)
  6. 更新 docker run 命令

    docker run -it \
               -e DISPLAY=$DISPLAY \
               -e XAUTHORITY=$XAUTH \
               -v $XSOCK:$XSOCK \
               -v $XAUTH:$XAUTH \
               --runtime=nvidia \
               --device=/dev/video0:/dev/video0 \
               nvcr.io/nvidia/pytorch:19.10-py3
    
    Run Code Online (Sandbox Code Playgroud)

注意:完成项目后,将访问控制恢复为其默认值 -xhost -local:docker

更多详细信息:将 GUI 与 Docker 一起使用

图片来源:使用 Tensorflow、OpenCV 和 Docker 进行实时和视频处理对象检测


归档时间:

查看次数:

264534 次

最近记录:

5 年,12 月 前