基于GUI环境的Docker?

基于GUI环境的Docker?,docker,qt,vagrant,configuration-management,Docker,Qt,Vagrant,Configuration Management,问题 我有一组客户机,它们是企业web应用程序的一部分。每台机器都运行相同的软件,这是一个连接到服务器的基于PyQT的web客户端。此客户端软件定期更新,我希望有一些配置/资源调配工具,允许在每台机器上具有相同的环境,从而在每台客户端机器上轻松部署和配置软件 问题是,我曾尝试使用Chef,但实际维护Chef知识和技能需要付出大量努力(我们没有专门的Ops人员),而且如果有第三方存储库(这是主要障碍),Chef配方可能会失败 我想尝试Docker来解决这个问题,但我不知道是否可以设置允许一些基于G

问题

我有一组客户机,它们是企业web应用程序的一部分。每台机器都运行相同的软件,这是一个连接到服务器的基于PyQT的web客户端。此客户端软件定期更新,我希望有一些配置/资源调配工具,允许在每台机器上具有相同的环境,从而在每台客户端机器上轻松部署和配置软件

问题是,我曾尝试使用Chef,但实际维护Chef知识和技能需要付出大量努力(我们没有专门的Ops人员),而且如果有第三方存储库(这是主要障碍),Chef配方可能会失败

我想尝试Docker来解决这个问题,但我不知道是否可以设置允许一些基于GUI的软件运行的图像/容器

问题


是否可以使用Docker为基于GUI的应用程序(PyQt/QT)提供开发/生产环境?如果是,第一步是什么?

我设法在容器中运行xeyes,并在容器外运行的X服务器中看到“窗口”。以下是方法:

我使用Xephyr运行嵌套的X服务器。这是不必要的,但大多数linux桌面在默认情况下不允许在其上运行远程应用(“这是如何在ubuntu上“修复”这个问题的)

安装Xephyr:

$ sudo apt-get install xserver-xephyr
运行Xephyr:

$ Xephyr -ac -br -noreset -screen 800x600 -host-cursor :1
这将创建一个新的800x600窗口,用作X服务器

查找计算机的“外部”地址。这是X服务器正在运行的位置:

$ ifconfig

docker0   Link encap:Ethernet  HWaddr 56:84:7a:fe:97:99  
          inet addr:172.17.42.1  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::5484:7aff:fefe:9799/64 Scope:Link
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:133395 errors:0 dropped:0 overruns:0 frame:0
          TX packets:242570 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:9566682 (9.5 MB)  TX bytes:353001178 (353.0 MB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:650493 errors:0 dropped:0 overruns:0 frame:0
          TX packets:650493 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:2506560450 (2.5 GB)  TX bytes:2506560450 (2.5 GB)

wlan0     Link encap:Ethernet  HWaddr c4:85:08:97:b6:de  
          inet addr:192.168.129.159  Bcast:192.168.129.255  Mask:255.255.255.0
          inet6 addr: fe80::c685:8ff:fe97:b6de/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:6587370 errors:0 dropped:1 overruns:0 frame:0
          TX packets:3716257 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:7405648745 (7.4 GB)  TX bytes:693693327 (693.6 MB)
不要使用127.0.0.1!你可以使用其他任何一种。我用172.17.42.1

创建包含以下内容的Dockerfile:

FROM ubuntu

RUN apt-get update
RUN apt-get install -y x11-apps

CMD ["/usr/bin/xeyes"]
构建它:

$ docker build -t xeyes .
然后运行它:

$ docker run -e DISPLAY=172.17.42.1:1.0 xeyes
请注意,我正在将DISPLAY环境变量设置为希望看到它的位置


您可以使用相同的技术将显示重定向到任何X服务器。

有许多解决方案可以在docker容器中运行GUI应用程序。例如,您可以使用SSH或VNC。但它们增加了一些开销和延迟。我发现的最好的方法就是将主机中X服务器使用的文件作为卷传递给容器。像这样:

docker run -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=unix$DISPLAY TheImage
然后,所有GUI应用程序都将从容器中运行


希望这有帮助

您可以使用来打包GUI应用程序。它还可以很好地支持应用程序的更新。您可以将DockerFile放入git repo中一次,然后在每个客户端上运行
subuser update all
,以便在需要更改图像时重建图像。

目前这个问题没有答案,但在Google上排名很高。其他答案基本上都是正确的,但有一点需要注意,那就是我是通过艰苦的学习才学会的,我想为其他人省去一些麻烦

Nasser Alshamari给出的答案是在Docker容器中运行GTK应用程序的最简单(也是最快)的方法——只需将X服务器的套接字作为Docker卷安装,并告诉Docker使用它即可

docker run -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=unix$DISPLAY TheImage
(我还建议传递
-u
标志,因为以root用户身份运行X11应用程序并不总是有效的,通常不建议这样做,尤其是在共享会话时)

这将适用于诸如
xterm
等应用程序以及基于GTK的应用程序。例如,如果您在Firefox(基于GTK)上尝试此操作,它将起作用(请注意,如果您已经在主机上运行Firefox,它将在主机上打开一个新窗口,而不是从容器中打开Firefox的新实例)

然而,您的回答特别询问PyQT。(或者至少没有很好地支持它)

如果尝试以这种方式运行基于QT的应用程序,可能会出现如下错误:

X Error: BadAccess (attempt to access private resource denied) 10
  Extension:    140 (MIT-SHM)
  Minor opcode: 1 (X_ShmAttach)
  Resource id:  0x12d
X Error: BadShmSeg (invalid shared segment parameter) 148
  Extension:    140 (MIT-SHM)
  Minor opcode: 5 (X_ShmCreatePixmap)
  Resource id:  0xb1
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
  Major opcode: 62 (X_CopyArea)
  Resource id:  0x2c0000d
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
  Major opcode: 62 (X_CopyArea)
  Resource id:  0x2c0000d
我之所以说“可能”,是因为我没有用足够多的Qt应用程序测试过这种方法,也没有深入研究Qt源代码,弄清楚为什么不支持这种方法。YMMV,您可能会很幸运,但是如果您希望从Docker容器中运行基于Qt的应用程序,您可能必须采用“老式”方法,并且或者

  • 在容器内运行sshd,打开X11转发,然后使用
    ssh-X
    (更安全)或
    ssh-Y
    (不安全,仅在完全信任容器化应用程序时使用)

  • 在容器内运行VNC,并使用VNC客户端从主机连接到容器


  • 在这两个选项中,我推荐第一个,但看看哪一个最适合您的情况。

    最近我尝试在docker中运行PyQt5应用程序。我学到的是,您不能以root用户身份运行应用程序(您必须创建普通用户)。当你们想在应用程序中播放音频/视频时,你们必须运行docker容器和组“audio”并安装声音设备。因此,要运行我的应用程序,我使用以下方法:

    docker run -it \
        -v /tmp/.X11-unix:/tmp/.X11-unix \
        -v $(pwd)/test:/app \
        -e DISPLAY=$DISPLAY \
        -u myusername \
        --group-add audio \
        --device /dev/snd \
        fadawar/docker-pyqt5-qml-qtmultimedia python3 /app/hello.py
    
    我花了一些时间,直到我弄清楚需要向容器中添加哪些包才能在其中运行PyQt应用程序,所以我创建了几个DockerFile(带有简单的演示应用程序),以方便其他人:

    Python 3+PyQt5:


    Python3+PyQt5+QML+QtMultimedia:

    以下是使事情正常运行所需遵循的基本步骤

  • 创建和运行Docker容器的步骤

    sudo nvidia docker run-it-d--privileged-e DISPLAY=$DISPLAY--name wakemeeup-v-v/dev:/dev-v/tmp/.X11 unix:/tmp/.X11 unix:rw nvidia/cuda:9.1-cudnn7-devel-ubuntu16.04 bash

  • 要启动docker容器

    sudo docker启动唤醒

  • 附加到docker容器的步骤

    xhost+local:root 1>/dev/null 2>&1
    docker exec-u$USER-it wakemeup/bin/bash
    xhost-local:root 1>/dev/null 2>&1

  • MIT-SHM是X服务器的扩展,它通过使用共享内存来实现更快的事务处理。Docker iso
    Process finished with exit code 134 (interrupted by signal 6: SIGABRT)
    
    QFactoryLoader::QFactoryLoader() checking directory path "/conda/envs/rapids/lib/python3.6/site-packages/PyQt5/Qt/plugins/platforms" ...
    QFactoryLoader::QFactoryLoader() looking at "/conda/envs/rapids/lib/python3.6/site-packages/PyQt5/Qt/plugins/platforms/libqeglfs.so"
    Found metadata in lib /conda/envs/rapids/lib/python3.6/site-packages/PyQt5/Qt/plugins/platforms/libqeglfs.so, metadata=
    {
        "IID": "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.3",
        "MetaData": {
            "Keys": [
                "eglfs"
            ]
        },
    ...
    ...
    ...
    Got keys from plugin meta data ("xcb")
    QFactoryLoader::QFactoryLoader() checking directory path "/conda/envs/rapids/bin/platforms" ...
    Cannot load library /conda/envs/rapids/lib/python3.6/site-packages/PyQt5/Qt/plugins/platforms/libqxcb.so: (libxkbcommon-x11.so.0: cannot open shared object file: No such file or directory)
    QLibraryPrivate::loadPlugin failed on "/conda/envs/rapids/lib/python3.6/site-packages/PyQt5/Qt/plugins/platforms/libqxcb.so" : "Cannot load library /conda/envs/rapids/lib/python3.6/site-packages/PyQt5/Qt/plugins/platforms/libqxcb.so: (libxkbcommon-x11.so.0: cannot open shared object file: No such file or directory)"
    qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
    This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
    
    Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, wayland-egl, wayland, wayland-xcomposite-egl, wayland-xcomposite-glx, webgl, xcb.
    
    Aborted (core dumped)
    
    xhost 127.0.0.1
    export DISPLAY=:0
    ssh -Y
    docker run -e DISPLAY=host.docker.internal:0 -it ros