web-dev-qa-db-fra.com

Docker pour les environnements GUI?

Problème

J'ai un ensemble de machines clientes qui font partie d'une application Web d'entreprise. Chaque machine exécute un logiciel identique, qui est un client Web basé sur PyQT qui se connecte à un serveur. Ce logiciel client est mis à jour régulièrement et j'aimerais avoir un outil de configuration/provisioning qui permet d'avoir le même environnement sur chaque machine et donc de faciliter le déploiement et la configuration du logiciel sur chacune des machines des clients.

Le problème est que j'ai essayé d'utiliser Chef, mais il faut beaucoup d'efforts pour maintenir les connaissances et les compétences de Chef (nous n'avons pas de gars Ops dédié) et de plus, une recette de Chef peut échouer si un référentiel tiers n'est plus disponible (c'est un bouchon principal).

Je voudrais essayer Docker pour résoudre le problème, mais je je ne sais toujours pas s'il est possible de configurer des images/conteneurs qui permettent à certains logiciels basés sur une interface graphique de fonctionner.

Question

Est-il possible d'utiliser Docker pour avoir un environnement de développement/production pour une application basée sur une interface graphique (PyQt/QT)? Si oui, quelles seraient les premières étapes pour aborder cela?

34
skanatek

Actuellement, cette question est sans réponse, mais elle est très bien classée sur Google. Les autres réponses sont pour la plupart correctes, mais avec quelques mises en garde que j'ai apprises à la dure, et je voudrais éviter aux autres des ennuis.

La réponse donnée par Nasser Alshammari est l'approche la plus simple (et la plus rapide) pour exécuter des applications GTK dans un conteneur Docker - montez simplement le socket du serveur X en tant que volume Docker et dites à Docker de l'utiliser à la place.

docker run -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=unix$DISPLAY TheImage

(Je recommanderais également de passer le -u <username-within-container> flag, car exécuter des applications X11 en tant que root ne fonctionne pas toujours et n'est généralement pas recommandé, surtout lors du partage de sessions).

Cela fonctionnera pour des applications telles que xterm, ainsi que pour les applications basées sur GTK. Par exemple, si vous essayez ceci avec Firefox (qui est basé sur GTK), cela fonctionnera (notez que si vous exécutez déjà Firefox sur l'hôte, il ouvrira une nouvelle fenêtre dans l'hôte plutôt qu'une nouvelle instance de Firefox). de l'intérieur du conteneur).

Cependant , votre réponse concerne spécifiquement PyQT. Il s'avère que Qt ne prend pas en charge le partage de sessions X de cette manière (ou du moins ne le prend pas bien en charge).

Si vous essayez d'exécuter une application basée sur QT de cette façon, vous obtiendrez probablement une erreur comme celle-ci:

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

Je dis "probablement" parce que je n'ai pas testé cette approche avec suffisamment d'applications Qt pour être sûr, ou creusé suffisamment dans le code source de Qt pour comprendre pourquoi cela n'est pas pris en charge. YMMV, et vous aurez peut-être de la chance, mais si vous cherchez à exécuter une application basée sur Qt à partir d'un conteneur Docker, vous devrez peut-être adopter l'approche "à l'ancienne" et soit

  1. Exécutez sshd dans le conteneur, activez le transfert X11, puis connectez-vous au conteneur à l'aide de ssh -X (plus sûr) ou ssh -Y (moins sécurisé, utilisé seulement si vous faites entièrement confiance à l'application conteneurisée).

  2. Exécutez VNC dans le conteneur et connectez-vous à celui-ci à partir de l'hôte avec un client VNC.

Entre ces deux options, je recommanderais la première, mais voyez celle qui convient le mieux à votre situation.

21
chimeracoder

Il existe de nombreuses solutions pour que les applications GUI s'exécutent dans un conteneur Docker. Vous pouvez utiliser SSH ou VNC par exemple. Mais ils ajoutent des frais généraux et des retards. Le meilleur moyen que j'ai trouvé est simplement de passer le fichier utilisé par le serveur X dans la machine hôte en tant que volume dans le conteneur. Comme ça:

docker run -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=unix$DISPLAY TheImage

Ensuite, toutes vos applications GUI s'exécuteront à partir du conteneur.

J'espère que cela t'aides!

9

Vous pouvez utiliser subuser pour empaqueter vos applications GUI. Il a également un bon support pour la mise à jour des applications. Vous pouvez placer vos Dockerfiles dans un dépôt git une fois, puis exécuter simplement subuser update all sur chaque client pour reconstruire les images lorsqu'elles doivent être modifiées.

1
timthelion

Voici les étapes de base à suivre pour que tout fonctionne bien,

  1. Pour créer et exécuter le conteneur 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

  2. Pour démarrer le conteneur Docker

    Sudo docker start wakemeup

  3. Pour attacher au conteneur 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

  4. Le MIT-SHM est une extension du serveur X qui permet des transactions plus rapides en utilisant la mémoire partagée. L'isolement de Docker le bloque probablement. Les applications Qt peuvent être forcées de ne pas utiliser l'extension. À l'intérieur du conteneur docker,

    nano ~/.bashrc export QT_X11_NO_MITSHM=1

  5. Source .bashrc

    source ~/.bashrc

J'espère que cela vous aidera

1
GPrathap

RESOLU - PyQt5-GUI dans Docker Container:

Activer Qt-Debug $ export QT_DEBUG_PLUGINS=1 ==> reproduire l'erreur ==> réinstaller la bibliothèque No such file or directory - répertoriée dans le message de débogage ==> répéter!

Je ne pouvais pas non plus exécuter PyQt5-GUI-app dans un conteneur Docker sans recevoir d'erreurs et lire d'abord tous les messages qu'il ne serait pas possible d'exécuter Qt dans des conteneurs Docker. Mais je pourrais le résoudre (au moins pour moi) ...

Système

J'exécute mon application PyQt5 dans un conteneur Docker avec socket /tmp/.X11-unix/ Partagé et affichage pour la visualisation GUI:

$ nividia-docker run --interactive --tty --env DISPLAY=$DISPLAY --volume /tmp/.X11-unix/:/tmp/.X11-unix/ <docker_iamge>

Erreur

L'initialisation de PyQt5.QtWidgets.QApplication A toujours conduit à l'erreur suivante:

Type "help", "copyright", "credits" or "license" for more information.
>>> from PyQt5.QtWidgets import QApplication
>>> app = QApplication([])
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)

En mode PyCharm Debug, l'erreur a renvoyé:

Process finished with exit code 134 (interrupted by signal 6: SIGABRT)

Solution

Méthode générale:

  • définir la variable d'environnement Qt-debug dans le terminal à conteneurs docker:
   $ export QT_DEBUG_PLUGINS=1
  • reproduire l'erreur dans le terminal docker (ou dans l'IDE), par exemple:
$ python
Python 3.6.8 |Anaconda, Inc.| (default, Dec 30 2018, 01:22:34) 
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.

>>> 
KeyboardInterrupt
>>> from PyQt5.QtWidgets import QApplication, QLabel
>>> app = QApplication([])
  • lire les messages de débogage imprimés sur le terminal, par exemple:
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)
  • trouver les packages <No such file or directory>.so.* et <coud not be loaded>, par exemple ici libxkbcommon-x11.so.0 Et libxcb. Réinstallez ensuite les packages/bibliothèques correspondants (la recherche des packages fonctionne avec apt-file --package-only search <filename> Ou conda/pip search ...). Dans mon cas, les bibliothèques suivantes étaient requises:
### lib no.1 ###
$ Sudo conda install --name <env_name> --force-reinstall libxcb    # or pip install ...
### lib no. 2 ###
$ apt-file --package-only search libxkbcommon-x11.so.0
libxkbcommon-x11-0
$ Sudo apt install libxkbcommon-x11-0 

Après avoir répété ce processus pour tous les messages de débogage reproduits séquentiellement et installé les 2 bibliothèques, je peux maintenant exécuter les applications PyQt5 à partir du conteneur Docker sur le bureau de ma machine locale.

0
drstoop