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

是否有任何图像设置vncserver或其他东西,以便您可以-例如-在Firefox周围添加额外的加速沙箱?


当前回答

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

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

其他回答

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

我推了一个图像,vnc/firefox,在这里:docker拉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'

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

对于Docker 18或更新版本:

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

对于Docker 1.3或更新版本:

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

对于1.3版本之前的Docker:

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

这里有很多关于如何将docker容器中的GUI应用程序连接到主机上运行的X服务器,或者如何运行虚拟X服务器并使用VNC连接到容器以访问它的很好的答案。

然而,还有另一种解决方案(这对kiosk或家庭影院非常有用)-你可以在docker容器内运行X服务器,并将视频输出到连接到主机的监视器上。

首先让我们创建一个docker卷来存储X11套接字:

docker volume create --name xsocket

现在我们可以用X服务器创建一个图像:

FROM ubuntu

RUN apt-get update && \
    DEBIAN_FRONTEND='noninteractive' apt-get install -y xorg

CMD /usr/bin/X :0 -nolisten tcp vt1

让我们构建并启动它,并将X11套接字存储在xsocket docker卷中:

docker build . -t docker-x-server:latest
docker run --privileged -v xsocket:/tmp/.X11-unix -d docker-x-server:latest

现在我们可以在另一个docker容器中运行一个GUI应用程序(耶!),并使用xsocket volume将其指向我们的X服务器:

docker run --rm -it -e DISPLAY=:0 -v xsocket:/tmp/.X11-unix:ro stefanscherer/xeyes

如果你需要输入(比如键盘),安装xserver-xorg-input-evdev包,并添加-v /run/udev/data:/run/udev/data,因为默认情况下容器中没有udev。

你甚至可以通过授予SYS_TTY_CONFIG功能并将一些设备绑定到容器中来摆脱——privileged标志:

docker run --name docker-x-server --device=/dev/input --device=/dev/console --device=/dev/dri --device=/dev/fb0 --device=/dev/tty --device=/dev/tty1 --device=/dev/vga_arbiter --device=/dev/snd  --device=/dev/psaux --cap-add=SYS_TTY_CONFIG  -v xsocket:/tmp/.X11-unix  -d  docker-x-server:latest

我通过以下步骤从USB摄像头使用opencv在docker中运行视频流:

Let docker access the X server xhost +local:docker Create the X11 Unix socket and the X authentication file XSOCK=/tmp/.X11-unix XAUTH=/tmp/.docker.xauth Add proper permissions xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge - Set the Qt rendering speed to "native", so it doesn't bypass the X11 rendering engine export QT_GRAPHICSSYSTEM=native Tell Qt to not use MIT-SHM (shared memory) - that way it should be also safer security-wise export QT_X11_NO_MITSHM=1 Update the docker run command 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

注意:当你完成项目时,返回默认值的访问控制- xhost -local:docker

更多细节:使用GUI的Docker

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

我来晚了,但对于不想走XQuartz道路的Mac用户,这里有一个工作示例,它使用Xvfb和VNC使用桌面环境(xfce)构建Fedora映像。这很简单,也很有效:

https://github.com/ddual/docker_recipes#fedora-with-an-x-window-system https://github.com/ddual/docker_recipes/tree/master/fedora_gui

在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"]

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

如果需要,请查看链接的自述文件以获得构建和运行命令。

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

它假设您使用带有X11转发的ssh连接到主机。

在主机的sshd配置中添加该行

X11UseLocalhost no

因此,主机上转发的X服务器端口在所有接口上都是开放的(不仅仅是lo),特别是在Docker虚拟接口docker0上。

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

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

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

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

我们可以定义一个别名:

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

然后像这样测试:

dockerX11run centos xeyes