Muy buenas lector. Esta página forma parte de la serie de introducción a Linux que te acabo de enlazar. Si ya has leído las partes introductorias relativas a distribuciones, entorno de escritorio o terminal, aquí ya entraremos en materia con temas algo más avanzados. En esta sección voy a centrarme específicamente en la tecnología de contenedores de software.
Primero te empezaré explicando, en muy pocas palabras, lo que es un contenedor y sus principales diferencias con respecto a una máquina virtual de las de toda la vida. Seguidamente verás los dos grandes grupos de contenedores que existen, y por último me centraré en las principales soluciones que puedes encontrar en GNU/Linux a día de hoy, y que considero más interesantes de conocer. ¡Vamos allá!
Tabla de contenidos:
- Tecnología de contenerización. Un poco de contexto
- ¿Qué es un contenedor?
- Diferencia entre una máquina virtual y un contenedor
- Contenedores de sistema y contenedores de aplicación
- Soluciones de contenedores soportadas en GNU/Linux
- Esto continua
Tecnología de Contenerización. Un Poco de Contexto
En el transcurso de los últimos años, el uso de soluciones de contenedores de software se ha generalizado en un gran numero de sectores, y no sin razón, puesto que aunque en mucos aspectos se asemejan a las tecnologías de virtualización tradicionales, ofrecen importantes ventajas, como veremos un poco más adelante.
La idea originaria detrás de las tecnologías de contenerización que tenemos hoy, aunque no lo parezca, es relativamente vieja. De hecho, data de 1979, momento en el que se introdujo un mecanismo denominado chroot en Unix. Linux aún no había nacido.
Una de las primeras implementaciones prácticas de esta tecnología llegó en el año 2000, con FreeBSD Jails. FreeBSD introdujo el concepto de jails o jaulas, con el propósito de poder disponer de diversas instancias de espacio de usuario, aisladas entre sí, pero construidas encima del mismo kernel del sistema operativo sobre el que se apoyan.
Después de esto, ya en el año 2008, la aparición de cgroups en el kernel Linux propició el lanzamiento de LXC como solución de contenedores de sistema. Esto sentó una parte muy importante de la base tecnológica que tenemos a día de hoy.
Docker, del que es difícil no haber oído hablar, nació poco más tarde, en el año 2013, y se construyó en gran medida sobre los cimientos de LXC, pero siguió su propio desarrollo como solución de contenedores de aplicación. Lo demás es ya historia mas o menos conocida.
¿Qué es un Contenedor?
Un contenedor de software es, en su esencia, una unidad de software estándar que corre encima de un sistema operativo host o anfitrión, y que provee un entorno de ejecución aislado a nivel de espacio de usuario. La idea es que todos los procesos que se ejecuten dentro del contenedor no tengan visibilidad sobre los procesos que haya fuera.
La tecnología de contenerización de software se apoya en tres tipos de tecnologías diferentes: virtualización, aislamiento y gestión de recursos. En un contexto de GNU/Linux, como el que nos ocupa, esto se traduce en el uso de varios de los mecanismos que proporciona el propio kernel, y que verás un poco más adelante, cuando entremos en el terreno de las distintas soluciones de contenedores.
Para conocer más en detalle cómo funciona un contenedor, creo que es más interesante empezar a verlo desde el punto de vista de las diferencias con respecto a las máquinas virtuales de toda la vida.
Diferencia entre una Máquina Virtual y un Contenedor
Tanto un contenedor como una máquina virtual representan imágenes de un sistema en ejecución (también denominado sistema guest o de invitado), corriendo encima de otro sistema (conocido como sistema host o anfitrión). La diferencia fundamental se encuentra en el tipo de aislamiento que ofrecen, y en el contenido de las imágenes que ejecutan.

Una máquina virtual hace uso de una tecnología de hipervisor para realizar una emulación del hardware. De esta manera, el sistema operativo anfitrión se encarga de virtualizar, a través del hipervisor, todo el set de recursos de hardware necesarios, como la CPU, la GPU o la memoria RAM, para poder
Esta tecnología permite literalmente que puedas ejecutar un sistema operativo al completo, kernel incluido, dentro de otro.
De este modo, si hay varias máquinas virtuales ejecutándose sobre el mismo sistema anfitrión, cada una de ellas correrá su propio sistema operativo independiente, con su propio kernel, y teniendo acceso a los recursos de hardware a que le de acceso el hipervisor.
En este contexto el aislamiento que proporciona el hipervisor entre el sistema operativo de invitado y el sistema operativo anfitrión es bastante mayor que el que se da entre un contenedor y el mismo sistema anfitrión. Por contra, una máquina virtual constituye también una unidad bastante más pesada en recursos, tanto en lo que respecta al tamaño en disco, como al uso de CPU y RAM.
En un contenedor no se realiza ninguna emulación a nivel de hardware, y los diferentes espacios de trabajo se construyen sobre el propio kernel del sistema operativo anfitrión. Es por este motivo que a menudo se dice que un contenedor proporciona una virtualización ligera.
Esto permite que puedas tener diferentes sistemas aislados entre sí, cada uno con su conjunto de aplicaciones y librerías, pero funcionando todos sobre el mismo kernel.
Debido a esto, un contenedor constituye una unidad mucho más ligera, ya que no debe contener un sistema operativo al completo, con su propio kernel, sino únicamente la parte relativa al espacio de usuario.
Un contenedor ocupa mucho menos espacio en disco, y supone un impacto mucho menor en recursos. Aun así, permite igualmente garantizar un entorno totalmente aislado a nivel de aplicaciones, que es lo que realmente buscamos en estos casos.
Contenedores de Sistema y Contenedores de Aplicación
Partiendo de la idea original de contenedores, y de las diferentes tecnologías e implementaciones que han ido surgiendo, hoy podemos distinguir claramente entre dos grandes grupos: los contenedores de sistema y los contenedores de aplicación.

Los contenedores de sistema son los que siguen el concepto original. Son los que aparecieron primero, y también los más próximos a las máquinas virtuales tradicionales, ya que en los dos casos el foco está puesto en el propio entorno que proveen. Ambas tecnologías juegan un rol similar, pero manteniendo las diferencias que ya has podido ver unas líneas más arriba.
En la línea conla definición original, un contenedor de sistema ofrece un entorno aislado a nivel de espacio de usuario, y permite instalar y ejecutar múltiples aplicaciones y servicios, con todo el conjunto de librerías asociadas.
Dado su parecido con respecto a las máquinas virtuales, los usos que se le pueden dar son muy parecidos, con la ventaja añadida de que suponen un impacto en recursos mucho menor con respecto a las primeras. Esto los ha hecho especialmente populares en entornos de TI, donde se necesite testear la compatibilidad de herramientas con diferentes sistemas operativos, correr ciertos servicios de forma aislada, etc.
Un contenedor de sistema puede ser desplegado partiendo de una imagen de cualquier distribución GNU/Linux. Una vez desplegado, cada contenedor dispondrá de todo el conjunto de herramientas del propio sistema operativo, a excepción del kernel.
Los contenedores de aplicación aparecieron bastante más tarde, y están mucho más alejados de las máquinas virtuales. Están pensados para la ejecución de un único servicio o aplicación, por lo qe en ellos, el principal foco de atención se traslada del entorno o sistema a la aplicación.
Como los contenedores de sistema, ofrecen igualmente un entorno aislado a nivel de espacio de usuario, pero ya no están pensados para dar cabida a múltiples servicios o aplicaciones, sino más bién para ejecutar una única aplicación, incluyendo, eso sí, todo el conjunto de librerías y dependencias que necesite para funcionar.
Dada esta naturaleza, los contenedores de aplicación se han vuelto enormemente populares en el ámbito del desarrollo de software, al facilitar enormemente las labores de empaquetado, testeo y despliegue de aplicaciones, permitiendo además una rápida portabilidad entre diferentes plataformas. Docker es el máximo exponente en este universo de contenedores.
Un contenedor de aplicación debe poder garantizar un comportamiento idéntico de la aplicación, con independencia del entorno o plataforma sobre el que se ejecuta el contenedor. Gracias a esto, una aplicación en desarrollo podrá ser testeada con las dependencias exactas con las que tendrá que acabar funcionando en producción, y también podrá ser desplegada y ejecutada en cualquier plataforma, sabiendo que funcionará exactamente igual en cualquier caso.
Soluciones de Contenedores Soportadas en GNU/Linux
Con toda esta introducción, creo que ya es un buen momento para conocer a las principales soluciones de contenerización que puedes encontrar a día de hoy en GNU/Linux, y que considero que son mas relevantes de conocer.
LXC y LXD

LXC y LXD son dos tecnologías hermanas de contenedores de sistemas, desarrolladas y mantenidas actualmente por Canonical, Ltd.
LXC o Linux Containers, es una herramienta de creación y ejecución de contenedores en GNU/Linux, que vió la luz en 2008 y empezó a poder funcionar a partir de la versión del kernel 2.6.29. Aunque fué inicialmente desarrollada por IBM, más tarde cogió el testigo Canonical, Ltd., y a día de hoy es la empresa que esponsoriza el proyecto, y presta la mayor parte de recursos, tanto a nivel de infraestructura como de desarrolladores.
LXC supone la primera implementación de contenedores en GNU/Linux que se basa enteramente en características presentes en el propio kernel, y también es justo mencionar que, pese a su ya veteranía, ha sentado buena parte de la base tecnológica sobre la cual se han acabado apoyando muchos otros proyectos, como LXD o Docker.
LXC entra dentro del ámbito de los contenedores de sistema, de los que ya te he hablado un poco antes. De este modo, un contenedor LXC permite que puedan correr dentro múltiples procesos y aplicaciones. De hecho, incluso permite ejecutar varios contenedores de tipo aplicación dentro de él.
A nivel de arquitectura, y como ya he mencionado, LXC se apoya en varias características del kernel Linux, que combinadas hacen posible la creación de estos entornos aislados, cada uno con su propio espacio de usuario, pero compartiendo el mismo kernel del sistema anfitrión. Entre esas características están Linux Namespaces, seccomp, los perfiles existentes de AppArmor o SELinux (dependiendo del caso), chroots y cgroups.
LXD o Linux Container Daemond es un motor de contenedores de software libre que nace de la mano de Canonical Ltd., la compañía que actualmente mantiene el proyecto. LXD fué lanzado en 2016, y se presenta como una evolución de LXC encaminada a facilitar el despliegue y gestión de contenedores por parte del usuario.
Aunque LXD es una evolución de LXC, lo cierto es que no re-escribe LXC, sino que más bien se construye encima de él. Básicamente le añade una capa por encima, para dotarlo de mayor potencia, escalabilidad, y una mejor experiencia de usuario. En este sentido, se podría decir que LXD es como un wrapper o envoltura de LXC.
LXD, de hecho, permite gestionar tanto contenedores de sistema como máquinas virtuales. A la hora de desplegar contenedores de sistema, dispone de plantillas con imágenes de una gran variedad de distribuciones GNU/Linux para correr en cada instancia de contenedor, de modo que puedas disponer de las herramientas propias de cada sistema, pero compartiendo el kernel con el sistema anfitrión.
A nivel de arquitectura, LXD sigue un esquema clásico cliente-servidor, con la presencia de un daemon que se encarga de mediar entre ambos. El daemon corre en segundo plano con privilegios de root en el sistema anfitrión, y es el que recibe las instrucciones del cliente a través de una REST API para coordinar todas las tareas en el backend, que es donde reside LXC.
El cliente de LXD, por otro lado, puede ejecutarse en el mismo sistema anfitrión donde tenemos el daemon, o en otro equipo físico diferente, puesto que se pueden comunicar de forma remota. Aunque el daemon de LXD únicamente puede ejecutarse en GNU/Linux, el cliente de LXD también puede ser instalado en macOS o Windows.
El proyecto LXD trabaja con dos ciclos de lanzamiento paralelos, uno para las ediciones LTS, que están soportadas por un largo periodo de tiempo, pero sin recibir nuevas características, y otro para las ediciones regulares, que generalmente se lanzan cada pocos meses, pero están soportadas por menos tiempo.
Docker

Docker es un motor de contenedores desarrollado por Docker, Inc., como proyecto de código abierto, y que desde su lanzamiento inicial en el año 2013, se ha hecho enormemente popular, al facilitar enormemente las tareas de despliegue y gestión de contenedores.
Al igual que LXD, Docker se construyó a partir de los cimientos de LXC, y se apoya también en varias de las características del kernel Linux. A pesar de este origen común, sin embargo, a lo largo de su evolución Docker ha seguido un camino separado de LXC y LXD, y se ha especializado en cubrir otro tipo necesidades.
Docker es una solución enmarcada dentro de lo que son los contenedores de aplicación, y si hay un sector en el que ha contribuido enormemente es justamente el del desarrollo de software. En este sentido, Docker permite empaquetar una aplicación y a todas sus dependencias en un entorno virtual aislado del sistema, de forma que pueda ser testeada, ejecutada y portada a cualquier entorno, garantizando el mismo funcionamiento.
A nivel de arquitectura, Docker está diseñada como una herramienta integral o todo-en-uno, con las ventajas e inconvenientes que ello conlleva. Funciona siguiendo el modelo clásico de cliente-servidor bajo la supervisión de un daemon central que se ejecuta en segundo plano en el sistema anfitrión, y es el cerebro que se encarga de coordinar todas las tareas, desde la creación de las imágenes hasta la ejecución de cada uno de los contenedores.
Con respecto al frontend, el cliente estándar de Docker funciona mediante la línea de comandos, aunque también existe un cliente de escritorio denominado Docker Desktop.
Como curiosidad, Docker impulsó el estándar Open Container Initiative (OCI), organismo del que a día de hoy forma parte, junto con otro puñado de empresas e instituciones. OCI se encarga de definir una serie de especificaciones comunes en el ámbito de la virtualización a nivel de sistema operativo.
Podman

Podman es un motor de contenedores nativo de Linux, y desarrollado por Red Hat como alternativa al ya veterano Docker. Al igual que este último, es un proyecto de código abierto, y se basa en el estándar Open Container Initiative (OCI), por lo que en este sentido las instrucciones de funcionamiento de cara al usuario son las mismas que en Docker u otras implementaciones que siguen este estándar.
Podman permite crear y gestionar contenedores al igual que Docker, pero también introduce el concepto de pods, ya visto en Kubernetes, y que representa básicamente una agrupación de varios contenedores compartiendo recursos comunes.
Podman ha nacido como un intento de reemplazar a Docker, pero de forma que la transición sea lo más suave posible por parte del usuario. Es por ello que, a nivel de usabilidad, guardan muchas similitudes. Además de esto, ambas soluciones pueden funcionar de lado sin problema.
A nivel de arquitectura es donde encontrarás más diferencias, ya que Podman se aleja del diseño todo-en-uno de Docker, y adopta una arquitectura modular, mucho más descentralizada. Esto hace que Podman utilice los componentes del sistema solo a medida que los va necesitando.
Aparte del diseño modular, Podman adopta un enfoque daemonless, en el sentido de que prescindiendo por completo del uso de daemons. Es por esto que a Podman se le considera como una solución bastante más segura que Docker, al eliminar el vector de ataque que supone la presencia de un daemon ejecutándose permanentemente en segundo plano y con permisos de root.
Podman también se dice que es rootless, en el sentido de que permite que la creación y ejecución de pods o contenedores pueda realizarse por parte de usuarios normales, sin permisos de root.
Dada esta arquitectura, Podman se apoya en systemd para la realización y coordinación de muchas de las tareas de gestión que en Docker recaen sobre su daemon, tales, como el arranque de un determinado contenedor, o al arranque de los servicios dentro del propio contenedor.
Para otras funciones diferentes, como la creación de las imágenes OCI de los contenedores, o la gestión de dichas imágenes, Podman se complementa con otras herramientas adicionales, como Buildah y Skopeo.
Pasando a la parte de usabilidad, aquí sí que nos encontramos con muchas similitudes con Docker. A nivel de cliente, la interacción del usuario es a través de la línea de comandos, y gran parte de los comandos son los mismos, por lo que un usuario de Docker no tendría mayores problemas para empezar a usar Podman.
Existe un proyecto actualmente en desarrollo denominado Podman Desktop, y permite que toda la interacción con Podman a nivel de imágenes, contenedores y pods pueda realizarse desde una interfaz gráfica.
Esto Continua
Como indico al principio, esta página forma parte de la serie de introducción a Linux y que sirve de punto de partida para todo el contenido relacionado con GNU/Linux que hay y habrá en el blog. A continuación iré enlazando el resto de páginas, a medida que las vaya teniendo preparadas.
- Las distribuciones
- Descarga e instalación
- La interfaz gráfica
- La interfaz de línea de comandos
- Administración de software y paquetes
- Aplicaciones imprescindibles
- Particiones y volúmenes
- Contenedores
- Seguridad y medidas de protección
- Opciones de portátiles con Linux
Espero que lo disfrutes:)