Escritorio gráfico en Docker mediante VNC

Docker 24 de jun. de 2023

Quizás en algún momento quieras probar una distribución Linux, pero no te apetezca tener que tener que usar VirtualBox, QEmu, VMWare, etc., puede que no quieras tener que buscar y descargar la ISO, asignando memoria, RAM, iniando y creando los discos y sus particiones, ni tener que hacer toda la instalación...‌‌Con Docker, puedes probar una distribución en modo texto simplemente usando Docker y usando su imágen desde un contenedor...

‌‌¿Pero que pasa si lo que quieres es además probar su entorno gráfico?‌‌
Pues que no hay problema. Podemos iniciar un servidor de VNC dentro del contenedor y exportar su Display para poderlo usar mediante un cliente de VNC.

Pasos para crear una imagen de Linux con escritorio gráfico

Paso 1: Crear el 'Dockerfile' y escoger distribución Linux

Nuestro fichero de configuración de docker con el que crearemos nuestra propia imagen, se debe basar en una imagen base del sistema operativo a usar.
En un directorio nuevo, crearemos un fichero con el nombre Dockerfile e iremos incluyendo en él todo lo que necesitemos para transformarlo en una distribución con entorno gráfico.

En mi caso usaré para la demostración Debian 12 'bookworm' como sistemas base, con lo que las primeras líneas a incluir serían:

# Partimos de la imagen de Debian (version bookworm)
FROM debian:bookworm

Paso 2: Instalar escritorio gráfico

Ahora tenemos que instalar es escritorio gráfico deseado, en el ejemplo vamos a instalar Mate Desktop, pero puedes escoger Cinnamon, LXDE, etc. Las líneas que debemos incluir en el Dockerfile serán las siguientes:

# ------ Mate Desktop (mediante MetaPaquete) + VNC ---
# Actualizamos primero
RUN apt-get -y update
# Instalamos Mate y Servidor VNC (modo no-interactivo)
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install -f mate-desktop-environment mate-desktop-environment-core mate-desktop-environment-extras tightvncserver
NOTA: Existen algunas distribuciones que ya disponen de todas las herramientas gráficas y/o escritorio preinstalado, en este caso solo instalaríamos el servidor de VNC (tightvncserver)

Paso 3: Configurar contraseña para acceso mediante VNC

En el proceso de creación de la imagen, podemos definir la contraseña que queremos usar para la conexión VNC, o dejar una por defecto. Para ello usaremos la opción ARG que es una variable que se utiliza en Docker unicamente en tiempo de creación de la imagen.
Esta contaseña la almacenaremos en el fichero de claves en el formato de VNC:

# Clave por defecto para la conexion VNC
ARG VNCPASSWORD=debian

# Almacenamos la clave en fichero para VNC
RUN mkdir /root/.vnc && \
  echo "$VNCPASSWORD"|vncpasswd -f > /root/.vnc/passwd && \
  chmod 0600 /root/.vnc/passwd

Paso 4: Usuario y fichero para entorno del servidor gráfico

Para poder usar VNC Server, de existir el fichero .Xresources en el carpeta home del usuario y además tener definido que usuario va a compartir su escritorio.
Para ello usamos la variable USER que deberá poder ser usada por el contenedor (mediante ENV conseguimos esto)  y el fichero necesario para X-Server:

# Fichero para servicios y recursos de X-Server
RUN touch /root/.Xresources

# Definimos usuario que mostrará su Escritorio gráfico
ENV USER=root

# Exponemos puerto para VNC
EXPOSE 5901

Paso 5: Iniciar el servidor VNC y no detener el contenedor

Sí únicamente ejecutasemos la llamada al servidor de VNC en el contenedor, se ejecutaría y luego se terminaría la ejecución.
Para evitar esto vamos a usar un truco muy simple, lanzar el servidor VNC y luego una bash para recibir comandos (aunque no recibamos nada)

Vamos a crear un fichero (entrypoint.sh) para realizar estos pasos, en el que pondremos el siguiente contenido:

#!/bin/bash
# Tamaño de Ventana a mostrar (se escalará)
# 1280x800, 1024x768, 980x650, etc
ANCHO=980
ALTO=650
GEOMETRIA=$ANCHO"x"$ALTO
# VNC server en Display 1 (:1)
/usr/bin/vncserver :1 -geometry $GEOMETRIA -depth 24

# Lanzamos una BASH para esperar comandos y evitar cerrar el contenedor
/bin/bash
entrypoint.sh

Ahora debemos copiar en la imagen este fichero y ejecutarlo cada vez que se inicie el contenedor, para ello escribiremos lo siguiente en el fichero Dockerfile:

# Copiar script de inicio de VNC
COPY ./entrypoint.sh /entrypoint.sh

# Permisos de ejecucion al scripte
RUN chmod +x /entrypoint.sh

# Ejecutar script cuanto se inicialice el contenedor
ENTRYPOINT ["/entrypoint.sh"]

Con estos 5 pasos ya tendriamos preparado el fichero para crear nuestra propia imagen con la distribución y escritorio gráfico deseado.

Creación de la Imagen

Debemos crear nuestra imagen para luego poderla usarla para iniciar el contenedor:

# Contruir imagen con clave por defecto (debian)
docker build --tag debian-mate:12 

# Contruir imagen con nuestra propia clave (ejemplo: SuperCl4v3)
docker build --tag debian-mate:12 --build-arg VNCPASSWORD=SuperCl4v3 .

Lanzar el contenedor con la distribucion con entorno gráfico

Ahora debemos iniciar el contenedor, debemos pasarle algunos parámetros extra para que el funcionamiento sea correcto:

docker run -d -ti --name desktop -v /dev/shm:/dev/shm -p 5901:5901 debian-mate:12
NOTA: Al iniciar el contenedor usaremos /dev/shm.
dev/shm es la implementación del concepto de "memoria compartida".
Permite que los datos sean compartidos entre diferentes programas que corren en Linux de una manera eficiente. Esto acelerará la ejecución de tareas en Linux.

Conectarse al contenedor mediante VNC

Con cualquier Cliente VNCd podemos conectarnos a nuestra distribución que se está ejecutando con escritorio gráfico.

Debemos saber la IP con la que se está ejecutando el contenedor y conectarnos al DISPLAY :1, que fue el que definimos como puerto para que se iniciase en nuestro fichero de entypoint.sh

# IP del contenedor 'desktop'
docker exec -ti desktop tail -1 /etc/hosts|awk '{print $1}'

	172.17.0.2
Obtener la IP del contenedor mediante su entrada en /etc/hosts

Una vez que sepamos la IP simplemente escribiremos lo siguiente:

# Conectar por VNC al contenedor:
vncviewer IP-Container:1

# Ejemplo con la IP obtenida anteriormente:
vncviewer 172.17.0.2:1

Cuando el Cliente VNC nos pida la contraseña, usaremos la que definimos en la construcción de la imagen (si no pusimos ninguna será 'debian' -por defecto-)

Debian 12 con Escritorio Gráfico ejecutándose en un contenedor Docker

Puedes revisar y descargar el proyecto completo desde mi GIT:

debian-desktop
Debian 12 with Desktop Environment: Mate Desktop

Etiquetas

Luis GuLo

🐧 SysAdmin GNU/Linux - 🐳 Docker - 🖥️ Bash Scripting - 🐪 Perl - 🐬 MySQL - 👥 Formador de TI - 👥 Formador de SysAdmin's - 💢 Ansible - ☁️ Cloud Computing - ❤️ Debian GNU/Linux