En los tiempos que corren con las nuevas tecnologías, mientras pestañeas ya han aparecido nuevos proyectos que marcarán la informática de los próximos años y otros que mueren, por el mero desuso. Entre toda esta vorágine, Docker, un sistema de contenedores, continuador de otros proyectos como las jaulas chroot y los Linux Containers (LXC), está revolucionado todo el mundo de la administración de sistemas. Y el fin de este artículo, primero de una serie sobre el tema, es justamente ése, averiguar el porqué de su éxito, además de su instalación, configuración e implementación.
Sobre Docker
Se trata de un proyecto que sigue la filosofía de desarrollo del código abierto (open source), que ha revolucionado la manera de desarrollar software gracias a la sencillez con la que permite gestionar contenedores. Los contenedores LXC son un concepto relativamente antiguo y utilizado desde hace tiempo por grandes empresas, como por ejemplo Google o Amazon, pero cuya gestión es, en cierta manera, complicada. A diferencia de éste, Docker define APIs y herramientas de línea de comandos que hacen de su creación, distribución y ejecución , una tarea más sencilla. Tal es así que se haya convertido en una herramienta fundamental tanto para desarrolladores como para administradores de sistemas.
Simplificando, podemos decir que un contenedor permite a un desarrollador, por ejemplo, empaquetar una aplicación con todas las partes que necesita, esto es, bibliotecas y dependencias, y usuarlo todo como si fuera un solo paquete. Simplificando aún más, si conocemos un poco el mundo de las máquinas virtuales, los contenedores funcionan de manera parecida. Son como una máquina virtual ligera pero con su propio sistema de ficheros, su propio espacio de usuarios y procesos o sus propias interfaces de red.
Veamos más a fondo sus ventajas y características:
Es portable
Un contenedor es ejecutado por lo que se denomina Docker Engine, un demonio (daemon) que es fácilmente instalable en prácticamente todas las distribuciones GNU/Linux. Su modo de uso es simple: un contenedor ejecuta una imagen de Docker, que es una representación del sistema de ficheros y otros metadatos que el contenedor va a utilizar para su ejecución. Una vez se ha generado la imagen del contenedor, ya sea en nuestra computadora o vía una herramienta externa, esta imagen podrá ser ejecutada por cualquier Docker Engine.
Inmutable
Ya sabemos que una aplicación la componen tanto su código fuente como las librerías del sistema operativo y del lenguaje de programación, necesarias para ejecutar dicho código. Estas dependencias dependen a su vez del sistema operativo donde nuestro código va a ser ejecutado. Esto ofrece un claro problema, ¿nos funcionará la aplicación en cualquier sistema operativo? En el caso de los contenedores, la cosa cambia. El proceso de instalación de dependencias de Docker no depende del sistema operativo, si no que este proceso se realiza cuando se genera una imagen del contenedor, tal y como hemos comentado en el párrafo anterior. Una imagen se genera una vez y puede ser ejecutada las veces que sean necesarias, y siempre se ejecutará con la misma versión del código fuente y sus dependencias, por lo que podemos decir que es inmutable. A esto le añadimos otra gran ventaja, es portable.
Ligero
Los contenedores que tenemos funcionando en la misma máquina, ya sea virtual o física, comparten entre ellos el mismo sistema operativo, pero cada contenedor es un proceso independiente, con su propio sistema de ficheros y sus propio espacio de ficheros. Esto hace la ejecución de contenedores sea mucho más ligera que otros mecanismos de virtualización. A modo ejemplo, una comparación con el sistema de virtualización VirtualBox. Este es capaz de hacer funcionan en un equipo convencional un puñado de máquinas virtuales, no demasiadas. En cambio, el mismo equipo es capaz de hacer funcionar cientos de contenedores sin mayor problema de rendimiento. Incluso, su gestión es más sencilla, como veremos más adelante.
Contenedores versus virtualización
Veamos antes de nada qué es la virtualización. Básicamente consiste en añadir una capa de abstracción a los recursos físicos con el objetivo de mejorar el uso de los recursos del sistema. Podemos crear varios entornos simulados, para diversos recursos. A modo de ejemplo, en el caso de un servidor físico, gracias a la virtualización, se pueden ejecutar varios sistemas operativos a la vez, para diversos propósitos.
Respecto a los diferentes tipos de virtualización:
- Virtualización completa: La máquina virtual no tiene acceso directo a los recursos físicos y requiere una capa superior para acceder a ellos. Es el caso de VirtualBox, Qemu, Hyper-V o los ESX de Vmware.
- Virtualización asistida por hardware: El hardware es el que facilita la creación de la máquina virtual y contra su estado. Sería KVM o Xen
- Virtualización a nivel de sistema operativo. Aquí se incluirían los contenedores.
En este último caso no es el hardware el encargado de aislar los recursos, sino el sistema operativo, además proporciona las herramientas necesarias para crear, controlar y manipular el estado de los contenedores.
Una vez aclarado esto, veamos las ventajas de los contenedores:
Rapidez
Los contenedores son capaces de compartir un solo núcleo y compartir bibliotecas de aplicaciones, esto ayuda a que utilicen menos recursos del sistema comparado con las máquinas virtuales. Además una máquina virtual puede tardar minutos para crearse y ponerse en marcha, en cambio un contenedor puede ser creado y lanzada en unos segundos. Incluso podemos decir que las aplicaciones contenidas tienen un rendimiento superior.
Portabilidad
Al estar las aplicaciones contenidas con todas las librerías necesarias, es perfectamente portable. Esto aporta múltiples ventajas a los equipo de desarrollo, ya que ayuda a aislar las dependencias por cada aplicación.
Seguridad
Los contenedores son compatibles con los principales sistemas de seguridad a nivel de kernel, como SELinux o GRSEC, entre otros. También ofrece grupos de control de acceso al demonio que controla la virtualización, restringiendo así posibles cambios que puedan hacerse en el sistema.
Conclusiones para esta pequeña introducción
Está claro, los contenedores aportan ligereza, portabilidad, flexibilidad y autosuficiencia, para los equipos de desarrollo. Ser una herramienta tan versátil nos ofrece un sinfín de posibilidades.
En el próximo capítulo entraremos en la parte técnico. Veremos cómo instalar Docker en un sistema GNU/Linux y algunos ejemplos sencillos de su uso. A medida que vayamos avanzando la cosa se pondrá más interesante, hablaremos de tecnologías como Docker Compose, que nos permitirá definir aplicaciones multi-contenedor de una manera sencilla y declarativa. Al final de esta serie mi intención es hablar de Kubernetes, una tecnología creada por Google, que nos servirá para gestionar y orquestar todos nuestros contenedores.
Nota: La imagen de funcionamiento de Docker la he extraído de su web oficial. La segunda imagen, con el diagrama, es de Wikipedia.
Gracias. A la espera del próximo capítulo.
Sumamente interesante. Gracias por explicarlo tan claramente.
Gracias por esta serie de artículos sobre un tema que está muy de actualidad y sobre el que conozco muy poco, así que me leeré estos artículos con interés 🙂
Una pregunta, David, sobre Docker y tu experiencia como administrador de sistema: Dices que esta tecnología es útil para entornos de desarrollo. Supongo que será para que cada desarrollador desarrolle exactamente sobre lo mismo y en las mismas condiciones, haciendo que sea más rápido montar el entorno de desarrollo y luego también no haya problemas de incompatibilidades con lo desarrollado por cada programador, no? Pero también Docker crees que puede ser útil en entornos de producción? o allí es mejor tener todo más optimizado a la máquina física sobre la que ejecuta el software, ya que la capa(s) extra que incorpora esta tecnología pueden lastrar al sistema (aunque sea poco) y marcan la diferencia en este tipo de entornos?