![无法在无头 docker 容器上打开显示,但可以在主机上打开显示](https://linux22.com/image/203372/%E6%97%A0%E6%B3%95%E5%9C%A8%E6%97%A0%E5%A4%B4%20docker%20%E5%AE%B9%E5%99%A8%E4%B8%8A%E6%89%93%E5%BC%80%E6%98%BE%E7%A4%BA%EF%BC%8C%E4%BD%86%E5%8F%AF%E4%BB%A5%E5%9C%A8%E4%B8%BB%E6%9C%BA%E4%B8%8A%E6%89%93%E5%BC%80%E6%98%BE%E7%A4%BA.png)
我正在研究无头系统,并尝试模拟显示器(特别是这样我可以使用搅拌机渲染无头系统,但问题更根本)。
我是模拟登录以创建 X 会话DISPLAY=:8 glxinfo
,并且可以在主机上运行,同时通过 ssh 连接到远程计算机。不幸的是,我没有能够做的就是让它在 docker 容器内运行。
容器很简单:
ARG CUDA_VERSION=11.4.2
ARG UBUNTU_VERSION=20.04
# Dev/deploy images build from the nvidia runtime
FROM nvidia/cudagl:${CUDA_VERSION}-runtime-ubuntu${UBUNTU_VERSION}
# Setup non-root user.
# Note that the UID needs to match the UID of the external user!
ARG USER_UID=<external_user_uid>
ARG USER_GID=${USER_UID}
ARG USERNAME=<external_username>
ARG HOME=/home/${USERNAME}
# Avoid warnings by switching to noninteractive
ARG DEBIAN_FRONTEND=noninteractive
# Configure apt and install packages
RUN apt-get update \
&& apt-get -y upgrade \
&& apt-get -y install \
# for demo
mesa-utils\
# nonroot
&& groupadd --gid ${USER_GID} ${USERNAME} \
&& useradd --uid ${USER_UID} --gid ${USER_GID} -m ${USERNAME} \
# Clean up
&& apt-get autoremove -y \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
USER ${USERNAME}
图像可以像这样启动:
# gpus flag isn't needed for the demo, but is part of my actual deployment
docker run --rm --gpus all --mount "source=/tmp/.X11-unix,target=/tmp/.X11-unix,type=bind,consistency=cached" -e DISPLAY=${DISPLAY} reprocontainer glxinfo
这在我的本地开发盒(我实际登录的地方)上成功运行,但是不是在我通过 ssh 连接的远程服务器上,它仍然报告:
No protocol specified
Error: unable to open display :8
我可以通过映射 .Xauthority(模拟登录的输出之一)文件并更改容器主机名来使其工作,如下所示:
docker run --rm -it --gpus=all --mount "source=/tmp/.X11-unix,target=/tmp/.X11-unix,type=bind,consistency=cached" -e DISPLAY=:8 -v "/home/<external_username>/.Xauthority:/home/<internal_username>/.Xauthority:rw" -u <internal_username> -h <external_hostname> glxinfo
虽然这有效,但无头会话需要额外的参数仍然令人困惑。我的猜测是,“真正的”登录做了一些额外的/不同的事情,以某种方式消除了对此的需要,但我不确定它可能是什么。
... 是什么赋予了?我缺少什么?
答案1
我的第一直觉是将标志添加--net=host
到容器中,以便它指向正确的位置。如果这没有帮助,那么解决方案可能超出了我的范围,但我可能会为您提供更有效的解释和解决方案:在 Docker 中运行的 GUI 应用程序的 X11 转发(在堆栈溢出上)。