Supongamos la siguiente situación:
Estamos en nuestro equipo de desarrollo ejecutando Ubuntu desktop (esta solución la he validado con Ubuntu 16.04 y Ubuntu 18.04), tenemos el servicio de LXD operativo y queremos ejecutar una aplicación gráfica (como por ejemplo un IDE) dentro de un contenedor.
La solución pasa por utilizar el concepto de device passthrough que se muestra en traspaso de dispositivos en lxc para aplicarlo a lxd y traspasar los dispositivos relacionados al servidor X dentro del contenedor.
Mapeando el identificador de usuario al contenedor
Como primer paso, y por una única vez en la vida de nuestro sistema, debemos permitir que los procesos de root de los contenedores que vayamos a crear pueda mapearse con nuestro identificador de usuario. Esto se hace con el siguiente comando.
$ echo "root:$UID:1" | sudo tee -a /etc/subuid /etc/subgid [sudo] contraseña para jose: root:1000:1
Crear el contenedor
Para este ejemplo crearemos un contenedor de nombre xtest con una imagen de Debian Stretch.
$ lxc launch images:debian/9 xtest Creando xtest Iniciando xtest
También, instalamos un entorno base mínimo para gestión de aplicaciones de escritorio.
$ lxc exec xtest -- apt update [Update command output] $ lxc exec xtest -- apt install x11-apps mesa-utils alsa-utils Reading package lists... Done Building dependency tree Reading state information... Done The following additional packages will be installed: bsdmainutils fontconfig-config fonts-dejavu-core groff-base kmod libasound2 libasound2-data libdrm-amdgpu1 libdrm-intel1 libdrm-nouveau2 libdrm-radeon1 libdrm2 libffi6 libfftw3-single3 libfontconfig1 libfreetype6 libgdbm3 libgl1-mesa-dri libgl1-mesa-glx libglapi-mesa libglew2.0 libglu1-mesa libgomp1 libice6 libllvm3.9 libpciaccess0 libpipeline1 libpng16-16 libsamplerate0 libsensors4 libsm6 libtxc-dxtn-s2tc libx11-xcb1 libxaw7 libxcb-dri2-0 libxcb-dri3-0 libxcb-glx0 libxcb-present0 libxcb-sync1 libxcursor1 libxdamage1 libxfixes3 libxft2 libxkbfile1 libxmu6 libxpm4 libxrender1 libxshmfence1 libxt6 libxxf86vm1 man-db ucf x11-common xbitmaps Suggested packages: cpp wamerican | wordlist whois vacation groff libasound2-plugins libfftw3-bin libfftw3-dev glew-utils pciutils lm-sensors less www-browser The following NEW packages will be installed: alsa-utils bsdmainutils fontconfig-config fonts-dejavu-core groff-base kmod libasound2 libasound2-data libdrm-amdgpu1 libdrm-intel1 libdrm-nouveau2 libdrm-radeon1 libdrm2 libffi6 libfftw3-single3 libfontconfig1 libfreetype6 libgdbm3 libgl1-mesa-dri libgl1-mesa-glx libglapi-mesa libglew2.0 libglu1-mesa libgomp1 libice6 libllvm3.9 libpciaccess0 libpipeline1 libpng16-16 libsamplerate0 libsensors4 libsm6 libtxc-dxtn-s2tc libx11-xcb1 libxaw7 libxcb-dri2-0 libxcb-dri3-0 libxcb-glx0 libxcb-present0 libxcb-sync1 libxcursor1 libxdamage1 libxfixes3 libxft2 libxkbfile1 libxmu6 libxpm4 libxrender1 libxshmfence1 libxt6 libxxf86vm1 man-db mesa-utils ucf x11-apps x11-common xbitmaps 0 upgraded, 57 newly installed, 0 to remove and 0 not upgraded. Need to get 27.7 MB of archives. After this operation, 192 MB of additional disk space will be used. Do you want to continue? [Y/n] y [Install command output]
Ajustes en el contenedor para soporte de aplicaciones gráficas
Ajustamos los mapeos dentro del contenedor según lo realizado en el primer punto.
$ lxc config set xtest raw.idmap "both $UID 1000"
Definimos la variable de entorno DISPLAY para que los procesos puedan hacer uso de las aplicaciones gráficas.
$ lxc config set xtest environment.DISPLAY ":0"
Transferimos los dispositivos asociados a los sockets que gestionan la comunicación con el servidor X.
$ lxc config device add xtest X0 disk path=/tmp/.X11-unix/X0 source=/tmp/.X11-unix/X0 Device X0 added to xtest $ lxc config device add xtest Xauthority disk path=/root/.Xauthority source=${XAUTHORITY} Device Xauthority added to xtest
Y finalmente, reiniciamos el contenedor.
$ lxc exec xtest -- poweroff $ lxc start xtest
Validando la configuración
Una vez realizados todos los pasos anteriores, estamos en condiciones de ejecutar aplicaciones gráficas dentro del contenedor. Por ejemplo, si ejecutamos:
$ lxc exec xtest -- xclock
Veremos que se abre una ventana con un reloj analógico donde se ve la hora UTC del sistema (salvo que antes hayamos aplicado lo que se muestra en Localización y zona horaria en contenedores LXD).