如何从docker容器内部查看GUI应用程序

vxf3dgd4  于 2023-06-21  发布在  Docker
关注(0)|答案(2)|浏览(117)

当我尝试运行一个GUI时,例如xclock,我得到错误:

Error: Can't open display:

我正在尝试使用Docker来运行ROS容器,我需要查看在其中运行的GUI应用程序。
我曾经使用Vagrant VM这样做过一次,并且能够使用X11完成它。
到目前为止,我已经尝试根据这里的信息将方式#1和#2放入docker文件中:http://wiki.ros.org/docker/Tutorials/GUI
然后我尝试在这里复制大部分dockerfile:https://hub.docker.com/r/mjenz/ros-indigo-gui/~/dockerfile/
以下是我当前的docker文件:

# Set the base image to use to ros:kinetic
FROM ros:kinetic

# Set the file maintainer (your name - the file's author)
MAINTAINER me

# Set ENV for x11 display
ENV DISPLAY $DISPLAY
ENV QT_X11_NO_MITSHM 1

# Install an x11 app like xclock to test this
run apt-get update 
run apt-get install x11-apps --assume-yes

# Stuff I copied to make a ros user
ARG uid=1000
ARG gid=1000

RUN export uid=${uid} gid=${gid} && \
    groupadd -g ${gid} ros && \
    useradd -m -u ${uid} -g ros -s /bin/bash ros && \
    passwd -d ros && \
    usermod -aG sudo ros

USER ros
WORKDIR /home/ros

# Sourcing this before .bashrc runs breaks ROS completions
RUN echo "\nsource /opt/ros/kinetic/setup.bash" >> /home/ros/.bashrc

# Copy entrypoint script into the image, this currently echos hello world
COPY ./docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
o7jaxewo

o7jaxewo1#

我个人的偏好是注入display变量并共享unix socket或X windows,如下所示:

docker run -it --rm -e DISPLAY \
  -v /tmp/.X11-unix:/tmp/.X11-unix \
  -v /etc/localtime:/etc/localtime:ro \
  my-gui-image

共享本地时间只是允许时区匹配,以及,我一直在使用这个电子邮件应用程序。
另一种选择是启动VNC服务器,在该服务器上运行您的应用程序,然后使用VNC客户端连接到容器。我不太喜欢这种方法,因为最终会在容器中运行两个进程,这使得信号处理和日志记录成为一个挑战。它的优点是应用程序更好地隔离,因此如果被黑客攻击,它无法访问您的X显示器。

hec6srdp

hec6srdp2#

我想

  • 主机系统为Linux
  • 窗口接口为X11

我会使用podman,但你可以在每个命令中用docker替换podman,我只是喜欢podman,从来没有用过docker。

    • 我的系统:**Opensuse Tumbleweedwithkde[Intel Optimus笔记本电脑]

解决方案

应用程序需要请求Xserver来显示其GUI元素。还有一个安全授权系统。
这个授权系统叫做xauth。xauth通常将会话cookie存储在*/home/username/. Xauthority * 文件中(通常但不总是)。

    • 检查当前使用的Cookie**
xauth list

输出看起来像这样,

localhost.localdomain/unix:0  MIT-MAGIC-COOKIE-1  99aaccf2d83177ddf581e2989ebbcea1
#ffff##:0  MIT-MAGIC-COOKIE-1  99aaccf2d83177ddf581e2989ebbcea1
    • 如果Xauthority不在通常的位置,请检查使用的是哪个权限文件**
xauth

如果标准文件未在使用中,则输出将类似于以下内容,

Using authority file /run/user/1000/xauth_Abcde

我们需要把这两样东西放进集装箱

      • MIT-MAGIC-COOKIE-1**-现在只将其视为协议或标识符。这对于每个会话都是恒定的。
      • 99aaccf2d83177ddf581e2989ebbcea1**-这个32个字母的密钥是会话密钥,或者你想给它起的任何花哨的名字。每个会话的密钥都是唯一的。

为了解决与显示相关的问题,我们需要做这五件事,

    • 1.**如果容器中没有. Xauthority文件,则创建一个. Xauthority文件,如我们的示例(debian)
    • 2.**将我们的会话密钥和协议添加到我们创建的. Xauthority文件
    • 3.**将DISPLAY环境变量传入容器
    • 4.**将主机Xserver socket(通常位于/tmp/.X11-unix)挂载到容器
    • 5.**设置网络为 * host *(显示渲染时需要)

这5个步骤将修复与显示相关的所有问题。

配置-场景示例

通过容器使用GUI运行firefox的示例。

    • 待办事项**
    • 1.**创建 *. Xauthority * 文件

在容器文件RUN touch .Xauthority中完成

    • 2.**将 * session key * 和 * protocol * 添加到我们创建的 *. Xauthority * 文件中

都作为环境变量传递
Containerfile ENV PROTOCOL=MIT-MAGIC-COOKIE-1中的协议集
session key作为参数传递给podman run--env KEY=$(xauth list | sed '2,$d'| tr -d '\n' | tail -c 32) \(不能在Containerfile中作为常量传递,因为它会在会话之间进行更改)
然后通过CMD xauth add ${HOST}:0 $PROTOCOL $KEY从Containerfile添加到 *. Xauthority *

    • 3.**将DISPLAY环境变量传入容器

作为参数传递给podman run--env DISPLAY \

    • 4.*挂载Xserver socket(通常位于/tmp/.X11-unix *)到容器

作为参数传递给podman run--mount type=bind,source=/tmp/.X11-unix,target=/tmp/.X11-unix,readonly \

    • 5.**设置网络类型为 * host *

在构建映像时配置podman build --network=host --tag guitest .

容器文件

FROM debian:latest

ARG DEBIAN_FRONTEND=noninteractive

RUN apt update && apt upgrade
RUN apt install --no-install-recommends --yes firefox-esr pipewire pipewire-alsa pipewire-pulse ffmpeg xauth

ENV PROTOCOL=MIT-MAGIC-COOKIE-1

ENV HOME /home/def
ENV USER def

RUN useradd --create-home --home-dir ${HOME} -G audio,video ${USER} && chown -R ${USER}:${USER} ${HOME}

WORKDIR ${HOME}
USER ${USER}

RUN touch .Xauthority

CMD xauth add ${HOST}:0 $PROTOCOL $KEY && firefox

Build命令

podman build --network=host --tag guitest .

使用构建好的镜像运行Container

podman run -it --rm --name guiapp \
--env DISPLAY \
--env KEY=$(xauth list | sed '2,$d'| tr -d '\n' | tail -c 32) \
--mount type=bind,source=/tmp/.X11-unix,target=/tmp/.X11-unix,readonly \
guitest
    • BINGO!**firefox GUI就在你眼前。
    • 免责声明**音频将无法在此示例中工作,需要一些额外的步骤才能使音频工作。

相关问题