Subuser: un Docker para el escritorio

Hoy andaba trasteando con Docker e intentando hacer que corriera una aplicación de escritorio, algo que no se puede hacer sin salirse del flujo que se espera de esta herramienta.

Docker es una plataforma que permite gestionar “contenedores”, algo similar a las máquinas virtuales de toda la vida, pero sin la sobrecarga de tener que simular otro sistema completo con su kernel y sus cosillas... Estos contenedores encontraron un entorno perfecto en los servidores, donde permiten montar más VPS, o donde permiten que cada micro-servicio corra de forma aislada sin necesidad de varias máquinas.

Sin embargo estos sistemas no estan orientados a las máquinas de “escritorio”, y se portan especialmente mal con X11. Esto es así poque para que un programa funcione sobre X11 sería necesario levantar un socket desde el anfitrion, es decir, desde fuera del contenedor, algo que no se puede automatizar a través de estas herramientas (aunque si con un shell script). Otra solución es levantar un servidor VNC dentro del contenedor, pero podemos intuir que el rendimiento es “limitado” :P.

Pues bien, hay un proyecto que pretende solventar este problema, este es Subuser. Podríamos decir, y ellos lo hacen, que Subuser es un Qubes OS ligero, simplemente da una capa de abstracción sobre Docker para permitir que aplicaciones de escritorio funcionen de forma transparente (o casi). Para ello implementaron un puente para la interfaz gráfica, y un sistema de gestión de permisos.

Podemos ver rápidamente como funciona, la instalación es muy sencilla, pero si usamos la rama master del git puede dar problemas, así que probablemente sea buena idea hacer checkout de la última release

1
$ git checkout 0.4  # Desde dentro del clon local, claro

Una vez instalado el resto es bastante sencillo, por ejemplo, si queremos levantar una instancia de xterm

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# Creamos un entorno para el contenedor 
$ subuser subuser add sample-term xterm
Adding subuser sample-term xterm
Verifying subuser configuration.
Verifying registry consistency...
Unregistering any non-existant installed images.
sample-term would like to have the following permissions:
 Description: A trivial terminal emulator
 Maintainer: Timothy Hobbs <timothyhobbs (at) seznam dot cz>
 Executable: /usr/bin/xterm
 Conservative permissions(These are safe):
  - stateful-home: To have its own home directory where it can save files and settings.
  - inherit-locale: To find out language you speak and what region you live in.
  - inherit-timezone: To find out your current timezone.
 Moderate permissions(These are probably safe):
  - gui:
   * To be able to display windows.
   * Is able to access the host's clipboard.
   * Is able to change the mouse's cursor icon.
  - access-working-directory: To access the directory from which it was launched.
  - allow-network-access: To access the network/internet.
A - Accept and apply changes
E - Apply changes and edit result
Please select an option:A # Aquí aceptamos los permisos
Checking if images need to be updated or installed...
Checking if subuser sample-term is up to date.
Installing xterm ...
Step 0 : FROM bbbb9023163704cee9c1fcb403f74098c409f9103d0c54f6eda309c54f70a355

# Y se pone a montar el contenedor...
# este proceso puede ser lento la primera vez ya que tiene que
# montar las imágenes intermedias

# Una vez acaba, solo queda lanzar el contenedor
$ subuser run sample-term

# Y en poco tiempo ya debería aparecer un xterm

Pero claro, no solo vamos a utilizar imágenes que vengan por defecto, montar las nuestras es bastante sencillo. Yo buscaba como meter aplicaciones gráficas en containers para poder ejecutar juegos de forma segura, hacer una imágen para esto se reduce a:

Crear un repositorio (un directorio donde meteremos todas las imágenes) y añadirlo as Subuser con

1
$ subuser repository add local ~/ruta/al/repositorio

Dentro del repositorio, creamos un directorio con el nombre que tendrá nuestra imágen, en el introduciremos un archivo permissions.json con la descripción del contenedor.

1
2
3
4
5
6
7
8
{
 "description"                : "Graphic and sound enabled games."
 ,"maintainer"                : "kenkeiras <kenkeiras (at) codigoparallevar dot com>"
 ,"executable"                : "/bin/bash"
 ,"gui"                       : {"cursors":true}
 ,"sound-card"                : true
 ,"basic-common-permissions"  : true
}

Nos interesa tener interfaz gráfica, sonido, el control del cursor y los permisos básicos, estos últimos bastante “light”. Todos los permisos están explicados en la documentación.

Se puede observar que el ejecutable que se indica es bash, esto es así para poder instalar algo a posteriori, de forma manual, no es óptimo, pero en mi caso era necesario, en caso de preparar una imágen para un juego en concreto podríamos indicar ahí el comando a ejecutar.

Y por último solo tendríamos que declarar en docker-image/SubuserImagefile como se generará el sistema de archivos del contenedor, en este caso sería suficiente con

1
FROM-SUBUSER-IMAGE libx11@default

Pero podría hacer cualquier cosa, es un Dockerfile. Además: ojo con el @default, indica que deriva de una de las imágenes que vienen por defecto, es necesario ponerlo si no pertenecen al mismo repositorio.

Y eso sería todo, ya podríamos lanzar nuestra imágen de la misma forma que hacemos con la de xterm, creando un entorno y después lanzandolo (pero añadiendo @local al nombre para indicar el repositorio).

TensorFlow con Python3 » « Ajustando el brillo de la pantalla en Awesome