Hernán's Blog

Docker 101: contenedores, kernel y capas

Si estás en el mundo del software, es muy probable que hayas usado Docker. Y si no, acá va una definición:

Docker es una plataforma para desarrollar, empaquetar y ejecutar contenedores. Palabra importante: contenedores, que hacen referencia a entornos aislados que incluyen todo lo necesario para que tu software funcione. Estos contenedores se crean a partir de imágenes, plantillas inmutables y reutilizables definidas mediante un Dockerfile. Gracias a esto, la misma imagen puede utilizarse en desarrollo, pruebas y producción, convirtiéndose en una unidad de trabajo consistente en un mundo distribuido.

Además, existen otros conceptos que suelen pasarse por alto: los volúmenes, que permiten persistir datos, y las redes, que conectan contenedores entre sí. Todo esto dentro de un ecosistema como Docker Hub, que ofrece miles de imágenes listas para usar.

Creo que sabiendo eso, ya podrías comenzar a trabajar e integrar contenedores en tu flujo de trabajo. Pero nosotros no nos detenemos aquí, vamos un poco más allá.

Cola de ballena emergiendo del océano

Antes de las ballenas

Antes de docker estaban las máquinas virtuales (VM), que son, en esencia, una emulación completa de un computador físico dentro de otro. Cada VM actúa como un equipo independiente, con su propia CPU virtual, memoria RAM y almacenamiento, lo que permite ejecutar sistemas operativos y aplicaciones de manera aislada y segura.

Podríamos pensar: ¿por qué no seguir ocupando máquinas virtuales? Pero hay un inconveniente arquitectónico: el peso y el volumen de la caja superan al del contenido; es decir, el sistema está desperdiciando recursos.

Cada instancia debe cargar y ejecutar un sistema operativo completo (Ubuntu, Debian, Windows u otro), lo que implica muchos recursos. Las imágenes de disco de las VM suelen ocupar gigabytes, y el proceso de arranque puede tardar varios minutos, incluso para aplicaciones simples. Esto genera una sobrecarga (overhead) que afecta tanto el rendimiento como la eficiencia del sistema.

Usando el kernel

Los contenedores, a diferencia de las VM, no emulan un computador completo ni requieren un sistema operativo independiente. En su lugar, comparten el kernel del sistema operativo host y aíslan solo los procesos y recursos necesarios para ejecutar una aplicación. Es una virtualización de nivel del sistema operativo. Esto elimina gran parte del overhead, permitiendo un uso más eficiente de los recursos y un despliegue casi instantáneo.

Una buena forma de visualizarlo es imaginar que una VM es una casa independiente: tiene sus propios cimientos, pilares, sistema eléctrico y plomería propia. En cambio, los contenedores son como departamentos en un edificio moderno. Cada departamento comparte la estructura principal, el sistema eléctrico y la plomería. Y aun así cada departamento tiene todo lo necesario para vivir cómodo y de forma independiente.

Edificio Azul

Gracias a esto tenemos los valores clave de Docker, particularmente la eficiencia y optimización de recursos versus las máquinas virtuales:

Namespaces y cgroups

Los contenedores trabajan sobre el kernel de forma aislada a través de dos mecanismos: namespaces y cgroups.

Un namespace abstrae los recursos globales del sistema para que los procesos crean que tienen su propia instancia aislada. Los cambios realizados en un recurso son visibles solo para los procesos que pertenecen al mismo namespace, permaneciendo invisibles para el resto.

Actualmente, el kernel de Linux tiene 8 tipos:

NamespaceRecurso que aísla
cgroupDirectorio raíz de los grupos de control (cgroup).
IPCComunicación entre procesos (System V IPC, colas de mensajes POSIX).
NetworkDispositivos de red, pilas de protocolos, puertos, etc.
MountPuntos de montaje del sistema de archivos.
PIDIdentificadores de procesos (permiten que un proceso sea el PID 1).
TimeRelojes de arranque (boot) y monotónicos.
UserIDs de usuario y de grupo (permite ser root dentro del namespace).
UTSNombre del host y nombre de dominio NIS.

Si los namespaces deciden qué puedes ver, los cgroups deciden cuánto puedes usar.

Los cgroups permiten asignar recursos del sistema (CPU, memoria, ancho de banda de red o una combinación) entre grupos de tareas definidos por el usuario (procesos). Y van más allá, permitiendo monitorear el consumo de los grupos configurados, restringir el acceso a ciertos recursos o establecer límites. Incluso, nos permite ajustar los límites y prioridades de forma dinámica. Con estos mecanismos logramos el aislamiento.

Docker opera sobre capas o layers inmutables

Una capa inmutable es un conjunto de archivos de solo lectura que registra un cambio de estado específico en la imagen. Al ser inalterables, Docker las reutiliza entre múltiples contenedores sin duplicar espacio en disco, garantizando que el entorno sea siempre idéntico y predecible (determinismo). Cualquier modificación posterior no edita la capa base, sino que genera una nueva sobre ella, protegiendo la integridad de la fuente original.

El trabajo entre capas es posible a través del concepto UnionFS. Este motor toma carpetas en distintas capas y las “une” virtualmente para que parezcan un sistema de archivos tradicional. De esta forma tenemos capas inmutables que operan en armonía, permitiendo levantar infraestructura desechable completamente replicable.

Capas inmutables de Docker

Comunicación y red

A través del network namespace se aísla la red. Cada contenedor opera como si tuviera su propia tarjeta de red y su propia IP. Basado en esto, para conectar los contenedores necesitamos un “switch”, un puente que permita la interacción, como si de una red física se tratara, generando un cableado virtual a través de una subred.

Pero hay un problema: las IPs son efímeras y, para no configurar IPs a cada rato, aparece el servidor DNS interno que se encarga de interceptar la petición y entregar la IP actual, o más bien el nombre del servicio. Estos 3 mecanismos nos permiten mantener la comunicación rápida, segura y confiable.

Docker y sus amigos

Sin embargo, Docker es solo la unidad de trabajo. En aplicaciones profesionales modernas (como las que usan Django o FastAPI), rara vez trabajamos con un solo contenedor; solemos necesitar una base de datos, backend, worker y un frontend trabajando en conjunto. Aquí es donde Docker Compose entra en escena como director de orquesta. Con un solo archivo de configuración, puedes definir una infraestructura completa para un producto digital.

Otras tecnologías como Kubernetes o Docker Swarm nos permiten orquestar a una mayor escala.

Con eso creo que ya son suficientes ballenas por un día, quizá por una semana, quizá por un buen tiempo. Espero que haya instruido de algo, y recordar que todas las tecnologías beben mucho de otras como sistemas operativos, virtualización y redes… y recuerda: si vas por ahí trabajando con Docker, no olvides crear tu .dockerignore.

Mas ballenas


Nota:

Docker Compose es excelente para desarrollo y pruebas, pero en producción no conviene poner la base de datos en un contenedor. Una base de datos necesita persistencia real, alta disponibilidad y buen tuning de rendimiento. Para producción, es más seguro usar servicios gestionados (AWS RDS, Cloud SQL) o VMs dedicadas con backups, réplicas y monitoreo serio.


Recursos

#docker #contenedores #virtualización

Estemos en contacto: conoce más sobre mí o conversemos en Twitter / X · Instagram .