在 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