在 Linux 容器中运行 GUI 应用程序

默认情况下,Docker 容器将无法运行 GUI 应用程序。

在此之前,X11 套接字必须首先转发到容器,因此可以直接使用。还必须转发 DISPLAY 环境变量:

docker run -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=unix$DISPLAY <image-name>

这将首先失败,因为我们没有设置 X 服务器主机的权限:

cannot connect to X server unix:0

最快(但不是最安全)的方法是允许直接访问:

xhost +local:root

完成容器后,我们可以回到原始状态:

xhost -local:root

另一种(更安全)的方法是准备一个 Dockerfile,它将构建一个新的映像,它将使用我们的用户凭据来访问 X 服务器:

FROM <iamge-name>
MAINTAINER <you>

# Arguments picked from the command line!
ARG user
ARG uid
ARG gid

#Add new user with our credentials
ENV USERNAME ${user}
RUN useradd -m $USERNAME && \
        echo "$USERNAME:$USERNAME" | chpasswd && \
        usermod --shell /bin/bash $USERNAME && \
        usermod  --uid ${uid} $USERNAME && \
        groupmod --gid ${gid} $USERNAME

USER ${user}

WORKDIR /home/${user}

从命令行调用 docker build 时,我们必须传递 Dockerfile 中出现的 ARG 变量:

docker build --build-arg user=$USER --build-arg uid=$(id -u) --build-arg gid=$(id -g) -t <new-image-with-X11-enabled-name> -f <Dockerfile-for-X11> .

现在,在生成一个新容器之前,我们必须创建一个具有访问权限的 xauth 文件:

xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f /tmp/.docker.xauth nmerge -

创建/运行此文件时,必须将其挂载到容器中:

docker run -e DISPLAY=unix$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix -v /tmp/.docker.xauth:/tmp/.docker.xauth:rw -e XAUTHORITY=/tmp/.docker.xauth