¿Para qué sirve Docker?

Quizá hayas escuchado hablar de Docker alguna vez. Se trata de una tecnología que promete permitir ejecutar aplicaciones y programas de ordenador en un lugar conocido como contenedor. A menudo lo usan para ejecutar aplicaciones de red que se ejecutan en servidores, pero en realidad puedes usarlo en tu propio ordenador personal para instalar programas como bases de datos, o aplicaciones alojadas que tengan interfaz web, de forma rápida y limpia.

Docker facilita el uso de cgroups

Docker se aprovecha de una tecnología presente en el núcleo Linux denominada cgroups. Esta tecnología permite limitar la cantidad de recursos que recibe un proceso en Linux, como el tiempo de CPU que recibe, la cantidad de RAM que puede usar, o incluso directorios de sistema a los que puede entrar.

Lo normal en tu ordenador es que cuando ejecutes un programa, éste tenga acceso a todos los recursos de la máquina. Eso significa que un proceso podría empezar a buscar el último decimal de pi y empezar a consumir un porcentaje importante de CPU que deje hambrientos otros programas en ejecución. O podría reservar suficiente memoria RAM como para dejar tiritando tu sistema. O entrar a cualquier directorio del disco duro para el que tenga permiso y consultar información.

Con cgroups, precisamente puedes aislar un proceso o grupo de procesos para limitar la cantidad máxima de CPU y memoria RAM que van a poder utilizar, e incluso separar la interfaz de red que usan para acceder a internet o cambiar su directorio raíz, de tal forma que sólo vean una porción pequeña del sistema de archivos para impedir que se metan donde no toca. También se puede limitar el uso de ciertas llamadas a sistema, como la posibilidad de que tengan su propia tabla de procesos en ejecución, para que no puedan ver qué procesos tienes en ejecución en tu máquina.

Y Docker precisamente lo que hace es aprovecharse de estas características y crear una forma conveniente de iniciar aplicaciones metidas en uno de esos cgroups. Para ello lo primero que hace es utilizar imágenes de Docker, que puedes ver precisamente como el conjunto de archivos que definirán el sistema de archivos virtual y limitado que verá Docker. Aquí es donde meterás los archivos que permiten funcionar tu programa. Esas imágenes también llevan metadatos, como el usuario con el que se debe ejecutar la imagen, o las variables de entorno a definir al lanzar el programa.

Una vez que tengas una imagen, puedes pedirle a Docker que la lance, creando un contenedor. Un contenedor es una ejecución de una imagen, y se llama así porque, al igual que un contenedor en un barco que transporta mercancías, todo lo que hay dentro de un contenedor está aislado de otros contenedores, y a menudo apilado en un gran sistema lleno de contenedores.

Pero una cosa muy simple que tienes que tener en cuenta es que lanzar un contenedor es simplemente una forma un poco bruta de pedirle a GNU/Linux que ejecute un programa, manteniendo el proceso bajo unas condiciones muy concretas y limitadas como las que contaba antes. La ventaja es que la operación es mucho más simple porque no hay que interactuar con cgroups a mano.

Docker no es virtualización

Es importante diferenciar Docker y cgroups de la virtualización. Cuando virtualizas, lo que haces es usar un programa que simula ser todo un ordenador completo, creando una máquina virtual. Hoy en día las máquinas virtuales son más rápidas gracias al uso de hipervisores y a cierta colaboración que ofrece la CPU del ordenador, pero esencialmente cuando instalas una distribución GNU/Linux en una máquina virtual, estás ejecutando un segundo kernel, simulado dentro de un programa que corres dentro de tu ordenador.

Pero al usar Docker, compartes el kernel de tu ordenador o servidor. En otras palabras, el mismo kernel que atiende las llamadas a sistema en los programas que ejecutas dentro de Docker es el que utilizas en tu máquina. Esta es la razón por la que si pruebas a ejecutar uname dentro de un contenedor de Docker en el que ese comando esté disponible, siempre va a reportar la misma versión del núcleo Linux que la que use tu máquina física, incluso aunque te lleves esa imagen de Docker a otros entornos con otras versiones de núcleo Linux.

Un contenedor de Docker puede pararse y reanudarse mediante operaciones como start y stop. Sin embargo, cuando detienes un contenedor de Docker, no lo estás congelando en el tiempo, que es lo que harías con una máquina virtual si suspendes su ejecución. Cuando detienes un contenedor de Docker verdaderamente detienes todos los procesos en ejecución, que se reanudarán la siguiente vez que se encienda el container.

Los overlays: el punto fuerte de Docker

Uno de los puntos fuertes de Docker es su sistema de overlays. Un overlay es una capa del sistema de archivos que se pone encima de otra, para agregar o quitar cosas.

Por ejemplo, si tienes un sistema de archivos en tu imagen de Docker que contiene 3 archivos, pero luego le pones encima usando un overlay otro sistema de archivos que contiene 2 archivos, al final solaparán y acabarás teniendo una imagen con 5 archivos. Puedes usar los overlays para agregar, modificar y quitar archivos.

Esto es fuerte porque permite crear imágenes reusables. Por ejemplo, existe una imagen de Docker llamada debian:slim, que contiene una instalación pequeña de Debian, con una shell y las herramientas mínimas para usar Docker. Mediante overlay, puedes agregar en otra imagen tus propios archivos de programa a la imagen debian:slim, y el resultado es una imagen que tiene Debian y tus archivos.

Lo normal es que una imagen final de Docker tenga varios overlays, a medida que se usan capas. Por ejemplo, la capa con Debian, la capa con un entorno de ejecución, y la capa con los archivos de programa. A este sistema, se le debe sumar también el volumen que guarda los archivos locales cuando ejecutas una imagen de Docker, para asegurarse de que algunas cosas no se pierdan cuando se detiene la ejecución de una imagen.

¿Por qué se usa tanto Docker?

Docker ha sido adoptado como una tecnología clave moderna para la industria informática y de servidores precisamente por la conveniencia a la hora de fabricar y compartir las imágenes.

Típicamente, instalar un programa en un servidor requería instalarlo a mano y configurarlo. Pero a veces, ese programa depende de paquetes que faltan en el gestor de paquetes del servidor, o pide versiones de una librería que son diferentes de las que aporta el sistema operativo.

Al usar una imagen de Docker, congelamos todo el entorno en el que se va a ejecutar el programa, y eso incluye tanto la distribución, como la versión de la distribución, como otras bibliotecas. Podrías usar la imagen de Docker de Fedora para fabricar una imagen de Docker de un programa que se ejecute sobre Fedora, y como la imagen ya trae todo lo necesario para arrancar el userland de Fedora, luego ejecutarlo en un entorno Docker en Debian, y funcionará de forma transparente.

Cómo instalar Docker en Debian 11 Bullseye

Docker es un software bastante popular presente hoy en día en muchos procesos de desarrollo de software y despliegue. Veamos cómo obtenerlo en workstations o servidores que ejecuten Debian 11.

Docker es un software bastante popular presente hoy en día en muchos procesos de desarrollo de software y despliegue. Su capacidad para ejecutar aplicaciones de forma aislada mediante contenedores lo ha convertido en un software vital en muchos servidores que, en los últimos años, han empezado a desplegar aplicaciones de forma «dockerizada» para ahorrarse el esfuerzo que supone instalar sobre el propio servidor todo el software necesario para ejecutar la aplicación.

También, gracias a la nube pública, hoy en día resulta habitual utilizar servicios donde en vez de administrar un servidor, tu proveedor cloud lo administra por ti y te ofrece directamente una forma de configurar y ejecutar contenedores de Docker desde su interfaz de usuario. A veces incluso como parte de un cluster de Kubernetes.

Instalar Docker en Debian 11 Bullseye

Si has pensado ingenuamente que podrías instalar Docker en Debian 11 usando apt install docker y has visto que no obtenías el resultado esperado, ya puedes ir pensando en desinstalar. Este paquete poco tiene que ver con el Docker que estás pensando.

Docker tiene una forma de «presentarse» bastante peculiar, por lo que antes de continuar tal vez sea conveniente contar las diferencias entre las distintas piezas de software que se hacen llamar «Docker».

  • Por un lado, Docker Engine es la parte principal del sistema de Docker. Contiene un demonio (dockerd) y una serie de aplicaciones de control (como el comando docker), y es lo que permite crear y ejecutar contenedores para lanzar aplicaciones de forma aislada, apoyándose en el sistema cgroups que forma parte del kernel Linux.
  • Por otro lado, Docker Desktop es un producto que cada vez más está siendo más promocionado por Docker Inc, la empresa que está detrás de Docker, que agrega una interfaz de usuario para controlar el Docker Engine y que facilita el proceso de instalación. Hay que entender que Docker Desktop no es de código abierto y que es un producto que al usarlo corporativamente en empresas más grandes podría ser de pago y requerir una licencia si no se cumplen los requisitos para tener acceso gratuito.

Si bien Docker Desktop hasta hace un tiempo era un producto exclusivo para los sistemas operativos Windows y MacOS, donde de todos modos es necesaria una máquina virtual que ejecute el kernel Linux para poder hacer uso del engine de Docker, ahora existe Docker Desktop para Linux, sujeto a los mismos términos de uso que sus hermanos para Windows y MacOS. Es por esta razón que en este post va a ser descartado como opción, y se va a hablar únicamente de Docker Engine.

Instalar Docker Engine desde los repositorios centrales de Debian

Debian 11 porta una versión de Docker Engine en sus repositorios principales, bullseye/main. Esta tal vez no sea la última versión de Docker disponible, pero es una versión relativamente reciente (la 20.11), que puede ser útil si no haces uso de las funciones más modernas de Docker.

Una de las ventajas de usar la versión de Docker Engine que hay en bullseye/main es que tu instalación de Docker tendrá más estabilidad, debido a que la política de actualizaciones de Debian congela las versiones de los paquetes y sólo proporciona correcciones de errores o de problemas de seguridad, así que puedes tener claro que tu instalación de Docker seguirá funcionando exactamente igual sin sorpresas todo el tiempo que Debian 11 continúe recibiendo soporte.

En cuanto a las desventajas: precisamente, que no vas a poder hacer uso de las funciones más recientes, que tal vez sólo estén disponibles en la versión de Docker Engine que distribuye Docker por su cuenta.

Para instalar Docker Engine desde los repositorios de Debian todo lo que tienes que hacer es ejecutar en una terminal con los permisos correspondientes

sudo apt install docker.io

El proceso de instalación incluye también la configuración de los demonios y de un grupo llamado docker. Si quieres poder utilizar Docker sin tener que escribir sudo, vas a tener que meter tu cuenta local habitual dentro del grupo docker, por ejemplo:

sudo /usr/sbin/usermod -aG docker [[tu usuario]]

Tratemos ahora de hacer una prueba para confirmar si se ha instalado bien o mal. Lanzamos un contenedor de la imagen hello-world, que es una imagen que se puede usar para depurar la instalación de Docker.

Resultado de ejecutar hello-world dentro de Docker

Si lejos de ver un mensaje de error, vemos que se ejecuta algo como lo logrado en la imagen, es que lo hemos hecho correctamente y que ya lo tenemos listo para utilizar. ¡Congratulaciones!

Instalar Docker Engine desde los repositorios de Docker

Si en su lugar nos interesase optar por una versión más reciente del engine, podemos agregar el repositorio oficial de Docker a nuestro sistema APT, e instalar Docker a través de ahí. Las instrucciones las tienes en su documentación oficial, pero consistirá en dar los siguientes pasos.

Primero instalaremos las dependencias necesarias para poder dar de alta la clave GPG que firma los paquetes que distribuye Docker en su repositorio oficial para Debian:

sudo apt update
sudo apt install ca-certificates curl gnupg lsb-release

Después, utilizaremos el siguiente comando para descargar e instalar la clave GPG de Docker:

sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

Para a continuación dar de alta el repositorio en el sistema.

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Finalmente, actualizaremos los paquetes de nuevo, e instalaremos Docker Engine:

sudo apt update 
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

Por último, validaremos de forma parecida a lo dicho en la sección anterior, que podemos ejecutar un contenedor de la imagen hello-world sin errores, y opcionalmente introduciremos a nuestro usuario principal en el grupo docker si pretendemos invocar comandos de Docker sin utilizar sudo.