Docker para entornos basados en GUI?


Problema

Tengo un conjunto de máquinas cliente que forman parte de una aplicación web empresarial. Cada máquina ejecuta software idéntico, que es un cliente web basado en PyQt que se conecta a un servidor. Este software cliente se actualiza regularmente y me gustaría tener alguna herramienta de configuración / aprovisionamiento que permita tener el mismo entorno en cada máquina y, por lo tanto, proporcionar una fácil implementación y configuración del software en cada una de las máquinas de los clientes.

El el problema es que he intentado usar Chef, pero se necesita mucho esfuerzo para mantener el conocimiento y las habilidades del Chef (no tenemos un tipo dedicado a Ops) y, además, una receta de Chef puede fallar si algún repositorio de terceros ya no está disponible (este es un tapón principal).

Me gustaría probar Docker para resolver el problema, pero todavía no sé si es posible configurar imágenes / contenedores que permitan algún software basado en GUI para operar.

Pregunta

¿Es posible usar Docker para tener un entorno de desarrollo/producción para una aplicación basada en GUI (PyQt/QT)? En caso afirmativo, ¿cuáles serían los primeros pasos para abordarlo?

Author: skanatek, 2014-06-07

5 answers

Actualmente esta pregunta no está respondida, pero está muy bien clasificada en Google. Las otras respuestas son en su mayoría correctas, pero con algunas advertencias que he aprendido de la manera difícil, y me gustaría evitar problemas a otros.

La respuesta dada por Nasser Alshammari es el enfoque más simple (y más rápido) para ejecutar aplicaciones GTK dentro de un contenedor de Docker: simplemente monte el socket para el servidor X como un volumen de Docker y dígale a Docker que lo use en su lugar.

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

(Yo también recomienda pasar la bandera -u <username-within-container>, ya que ejecutar aplicaciones X11 como root no siempre funciona, y generalmente no se recomienda, especialmente cuando se comparten sesiones).

Esto funcionará para aplicaciones como xterm, así como para aplicaciones basadas en GTK. Por ejemplo, si prueba esto con Firefox (que está basado en GTK), funcionará (tenga en cuenta que si ya está ejecutando Firefox en el host, se abrirá una nueva ventana en el host en lugar de abrir una nueva instancia de Firefox desde dentro de la contenedor).

Sin embargo , su respuesta pregunta sobre PyQt específicamente. Resulta que Qt no soporta compartir X sesiones de esta manera (o al menos no lo soporta bien).

Si intenta ejecutar una aplicación basada en QT de esta manera, probablemente obtendrá un error como el siguiente:

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

Digo "probablemente" porque no he probado este enfoque con suficientes aplicaciones de Qt para estar seguro, o profundizado en el código fuente de Qt lo suficiente como para averiguar por qué esto no es compatible. YMMV, y usted puede tener suerte, pero si usted está buscando para ejecutar una aplicación basada en Qt desde dentro de un contenedor Docker, es posible que tenga que ir el enfoque "anticuado" y ya sea

  1. Ejecute sshd dentro del contenedor, active el reenvío X11 y luego conéctese al contenedor usando ssh -X (más seguro) o ssh -Y (menos seguro, use solo si confía plenamente en la aplicación en contenedores).

  2. Ejecutar VNC dentro del contenedor, y conéctese a él desde el host con un cliente VNC.

Entre esas dos opciones, recomendaría la primera, pero vea cuál funciona mejor para su situación.

 16
Author: chimeracoder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-08 20:37:16

Hay muchas soluciones para tener aplicaciones GUI ejecutándose en un contenedor docker. Puede usar SSH o VNC, por ejemplo. Pero añaden algunos gastos generales y retraso. La mejor manera que encontré es simplemente pasar el archivo utilizado por el servidor X en la máquina host como un volumen al contenedor. Así:

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

Entonces todas sus aplicaciones GUI se ejecutarán desde el contenedor.

Espero que Esto ayude!

 8
Author: nasser alshammari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-07 15:18:57

Logré ejecutar xeyes en un contenedor y ver la "ventana" en un servidor X que se ejecuta fuera del contenedor. He aquí cómo:

Usé Xephyr para ejecutar un servidor X anidado. Esto no es necesario, pero la mayoría de los escritorios linux no permiten ejecutar aplicaciones remotas en ellos por defecto (aquí's cómo "arreglar" esto en ubuntu).

Instalar Xephyr:

$ sudo apt-get install xserver-xephyr

Ejecutar Xephyr:

$ Xephyr -ac -br -noreset -screen 800x600 -host-cursor :1

Esto crea una nueva ventana de 800x600, que actúa como un servidor X.

Encuentra una dirección" externa" de tu máquina. Aquí es donde se ejecuta el servidor 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)

No utilice 127.0.0.1! Puedes usar cualquiera de los otros. Voy a usar 172.17.42.1.

Cree un Dockerfile con el siguiente contenido:

FROM ubuntu

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

CMD ["/usr/bin/xeyes"]

Construirlo:

$ docker build -t xeyes .

Y ejecutarlo:

$ docker run -e DISPLAY=172.17.42.1:1.0 xeyes

Tenga en cuenta que estoy configurando la variable de entorno DISPLAY donde quiero verla.

Puede utilizar la misma técnica para redirigir la pantalla a cualquier servidor X.

 3
Author: ivant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-13 12:22:42

Puede usar subusuario para empaquetar sus aplicaciones GUI. También tiene un buen soporte para actualizar aplicaciones. Puedes poner tus Dockerfiles en un repositorio git una vez, y luego simplemente ejecutar subuser update all en cada cliente para reconstruir las imágenes cuando necesiten ser cambiadas.

 1
Author: timthelion,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-16 11:54:45

Recientemente intenté ejecutar la aplicación PyQt5 en docker. Lo que aprendí es que no se puede ejecutar la aplicación como root (hay que crear usuario normal). Cuando desea reproducir audio / video en la aplicación, debe ejecutar el contenedor docker con el grupo "audio" y montar el dispositivo de sonido. Así que para ejecutar mi aplicación utilizo esto:

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

Paso algún tiempo hasta que descubrí qué paquetes necesito agregar a mi contenedor para ejecutar la aplicación PyQt en él, así que creé algunos Dockerfiles (con una aplicación de demostración simple) para hacerlo más fácil para los demás:

Python 3 + PyQt5: https://github.com/fadawar/docker-pyqt5

Python 3 + PyQt5 + QML + QtMultimedia: https://github.com/fadawar/docker-pyqt5-qml-qtmultimedia

 1
Author: fadawar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-08 20:19:22