Saltar al contenido

Qué es un contenedor

Qué problema vino a resolver el contenedor, por qué no es una máquina virtual pequeña, la diferencia entre imagen y contenedor, y de qué piezas se compone Docker.

El problema que resuelve un contenedor

Una aplicación casi nunca es solo su código. Necesita una versión concreta del intérprete o de la máquina virtual del lenguaje, unas bibliotecas del sistema, unas variables de entorno y unos ficheros de configuración. Cuando ese conjunto se instala a mano en cada servidor, acaba pasando siempre lo mismo: funciona en el equipo de quien la desarrolló y falla en preproducción, y nadie sabe exactamente en qué se diferencian las dos máquinas.

Un contenedor es la respuesta a eso. Empaqueta la aplicación junto con todo lo que necesita para ejecutarse, salvo el núcleo del sistema operativo, en una unidad cerrada que se arranca igual en cualquier anfitrión que sepa ejecutar contenedores. Lo que se prueba es exactamente lo que se despliega, byte a byte.

  • Portabilidad: la misma unidad se ejecuta en el portátil del desarrollador, en el servidor de pruebas y en producción.
  • Aislamiento: cada contenedor ve su propio sistema de ficheros, sus procesos y su red, y no puede pisar a los demás.
  • Densidad: en un mismo servidor caben muchos más contenedores que máquinas virtuales, porque no duplican el sistema operativo.
  • Rapidez: arrancar un contenedor es arrancar un proceso, cuestión de segundos, no de minutos.
  • Inmutabilidad: no se parchea un contenedor en marcha, se reconstruye la imagen y se sustituye. Eso elimina la deriva entre servidores.

La frase que resume la idea: el contenedor traslada el problema de «cómo instalo esto en cada servidor» a «cómo construyo esto una sola vez».

Para el examen

  • Qué problema resuelve: el «en mi máquina funciona»

  • Cómo: empaqueta la aplicación con sus dependencias

  • Qué consigue: entorno idéntico en desarrollo y en producción

Contenedor frente a máquina virtual

Esta es la comparación que más se pregunta, y la respuesta cabe en una frase: la máquina virtual virtualiza el hardware y el contenedor virtualiza el sistema operativo. Un hipervisor le presenta a cada máquina virtual un ordenador completo simulado, y encima de ese ordenador hay que instalar un sistema operativo entero, con su núcleo. Un contenedor no lleva núcleo: usa el del anfitrión, compartido con todos los demás contenedores de esa máquina.

AspectoMáquina virtualContenedor
Qué se virtualizaEl hardware, mediante un hipervisorEl sistema operativo, mediante el propio núcleo
NúcleoCada máquina lleva el suyoSe comparte el del anfitrión
ContenidoSistema operativo completo más la aplicaciónSolo la aplicación y sus dependencias
Tamaño típicoGigabytesDecenas o cientos de megabytes
ArranqueMinutos: hay que arrancar un sistema operativoSegundos: es lanzar un proceso
AislamientoFuerte: fronteras a nivel de hardware virtualMás débil: fronteras a nivel de núcleo
Sistemas distintosPuede ejecutar Windows sobre Linux o al revésEl contenedor tiene que ser compatible con el núcleo del anfitrión

El aislamiento del contenedor lo proporcionan dos mecanismos del núcleo de Linux. Los namespaces le dan a cada contenedor su propia visión del sistema: sus procesos, su sistema de ficheros, su nombre de máquina y su pila de red, de modo que no ve nada de lo que hay fuera. Los cgroups, o grupos de control, limitan cuántos recursos puede consumir: cuánta CPU, cuánta memoria, cuánta entrada y salida.

De ahí sale la única limitación de fondo. Como el núcleo es compartido, en un anfitrión Linux solo se pueden ejecutar contenedores Linux. Cuando se dice que Docker corre sobre Windows o sobre macOS, lo que hay debajo es una máquina virtual ligera con Linux dentro, y los contenedores viven en ella. Las dos tecnologías no son alternativas excluyentes: lo habitual es ejecutar contenedores dentro de máquinas virtuales.

Si una pregunta describe algo que no lleva sistema operativo completo, comparte el núcleo del anfitrión y arranca en segundos, está describiendo un contenedor. Si habla de hipervisor y de sistema operativo invitado, es una máquina virtual.

Para el examen

  • Núcleo: el contenedor comparte el del anfitrión

  • Arranque y tamaño: segundos y megabytes

  • Su contrapartida: aísla menos que una máquina virtual

Imagen y contenedor no son lo mismo

Es la distinción que más confunde al empezar y la que hay que tener clarísima. Una imagen es una plantilla de solo lectura: un paquete inmutable con el sistema de ficheros y la configuración de arranque de una aplicación. Un contenedor es una instancia en ejecución de una imagen. La relación entre las dos es exactamente la que hay entre un programa en disco y un proceso, o entre una clase y un objeto.

ImagenContenedor
Qué esPlantilla de solo lecturaInstancia en ejecución de una imagen
Se puede modificarNo, es inmutableSí, pero solo en su capa de escritura
Cuántos hayUna imagen, muchos contenedores a la vezCada uno independiente de los demás
Dónde viveEn el registro y en la caché localEn el anfitrión que lo ejecuta
Se identifica porNombre y etiqueta, por ejemplo nginx:1.27Un identificador propio y, si se le da, un nombre

Una imagen no es un fichero monolítico: está formada por capas apiladas, y cada instrucción de construcción añade una. Esas capas se comparten entre imágenes, de modo que si diez imágenes parten de la misma base, esa base se guarda y se descarga una sola vez. Al arrancar un contenedor, el motor apila encima de las capas de solo lectura una capa fina de escritura que es la única que ese contenedor puede modificar.

Consecuencia práctica de esa capa de escritura: todo lo que un contenedor escriba dentro de sí mismo desaparece cuando se le borra. Para conservar datos hacen falta volúmenes.

Para el examen

  • Imagen: la plantilla de solo lectura

  • Contenedor: su ejecución, con una capa de escritura encima

  • Relación: de una imagen salen muchos contenedores

El registro de imágenes

Un registro es el almacén desde el que se publican y se descargan imágenes. Funciona como un repositorio de paquetes: la imagen se construye una vez, se sube al registro, y desde ahí se la baja cualquier servidor que tenga que ejecutarla. El registro público por defecto de Docker es Docker Hub, y la instalación lo trae ya configurado, de modo que pedir una imagen por su nombre a secas la busca allí.

En una organización, lo normal es tener además un registro privado propio, tanto para las imágenes que no se quieren publicar como para no depender de la disponibilidad ni de los límites de descarga de un servicio externo. En el anfitrión, las imágenes descargadas y los contenedores se guardan bajo /var/lib/docker.

Una imagen se nombra con un repositorio y una etiqueta separados por dos puntos. La etiqueta suele ser la versión, y si no se indica ninguna se asume latest, lo que es una fuente de sorpresas: latest no significa «la última», significa «la que alguien haya etiquetado así», y puede cambiar bajo los pies de un despliegue.

bash
# Descargar una imagen del registro por defecto (Docker Hub)
docker pull postgres:16

# Descargar de un registro privado: el nombre lleva delante el servidor
docker pull registro.llegandoalcorte.com/api-temario:2.4.1

# Autenticarse contra un registro privado
docker login registro.llegandoalcorte.com

# Etiquetar una imagen local y publicarla
docker tag api-temario:2.4.1 registro.llegandoalcorte.com/api-temario:2.4.1
docker push registro.llegandoalcorte.com/api-temario:2.4.1

En producción nunca se despliega una imagen etiquetada como latest. Se fija la versión exacta, que es lo único que hace reproducible un despliegue.

Para el examen

  • Qué hace: guarda y distribuye imágenes

  • push y pull: subir y descargar

  • Docker Hub: el registro público

Las piezas de Docker

Docker no es un solo programa. El comando docker que se teclea es únicamente un cliente: no ejecuta contenedores, sino que envía órdenes a un demonio que corre en segundo plano y es quien hace el trabajo de verdad. Entender ese reparto explica cosas que si no parecen mágicas, como que el cliente pueda administrar contenedores de otra máquina.

PiezaPapel
Cliente dockerLa línea de comandos. Traduce lo que teclea el administrador en llamadas a la API del demonio.
Demonio dockerdEl servicio que atiende esas llamadas: construye imágenes, gestiona redes y volúmenes y ordena arrancar contenedores.
containerdEl gestor del ciclo de vida de los contenedores y de las imágenes, un nivel por debajo del demonio.
runcEl motor que crea de verdad el contenedor, montando los namespaces y los cgroups del núcleo.
RegistroEl almacén externo del que se descargan y al que se publican las imágenes.

Ese despiece no es un detalle de implementación de un producto concreto: responde a un estándar, la OCI, del que se ocupa el punto siguiente. Y ese estándar es la razón de que Docker, que fue el primero y sigue siendo el más conocido, no sea el único: hoy conviven varios motores compatibles, y el más extendido de las alternativas es Podman, que además puede ejecutar contenedores sin demonio y sin privilegios de administrador. Por debajo de todos ellos siguen estando las mismas piezas del núcleo de Linux, que también usan directamente tecnologías anteriores como LXC y OpenVZ.

bash
# Resumen del estado del motor: contenedores, imagenes, registro y rutas
docker info

# Version del cliente y del demonio, que pueden no coincidir
docker version

# Espacio ocupado por imagenes, contenedores y volumenes
docker system df

El comando docker es un cliente. Si el demonio no está en marcha, cualquier orden falla con un error de conexión, no con un error de la orden en sí.

Para el examen

  • Cliente: manda las órdenes

  • Demonio: construye y ejecuta

  • Si el demonio no está en marcha: cualquier orden falla, por correcta que sea

El estándar OCI y sus tres especificaciones

La Open Container Initiative es el proyecto de la Linux Foundation que normaliza el mundo de los contenedores. Su objetivo es que un contenedor no dependa del fabricante que lo creó, y para conseguirlo publica tres especificaciones que cubren las tres cosas que se pueden hacer con un contenedor: ejecutarlo, empaquetarlo y repartirlo.

EspecificaciónQué normaliza
OCI Runtime SpecificationCómo se ejecuta un contenedor a partir de un paquete: qué es un contenedor para el sistema y qué operaciones admite. La implementación de referencia es runc.
OCI Image FormatEl formato de la imagen, para que una misma imagen se pueda usar con Docker o con cualquier otro motor.
OCI Distribution SpecificationCómo se distribuyen las imágenes, lo que afecta a los repositorios: Docker Hub, Artifactory, Nexus o Archiva hablan todos el mismo protocolo.

runc es la pieza que implementa la especificación de ejecución y es el corazón de casi cualquier contenedor: por él pasa la creación real de los namespaces y los cgroups, use quien use el motor de arriba.

Junto a la OCI conviene situar la CRI, Container Runtime Interface, que se confunde con ella y no es lo mismo ni la publica la misma organización. La CRI es el interfaz que define Kubernetes para hablar con el motor que ejecuta los contenedores. Al principio Kubernetes solo funcionaba con Docker; al abrirse esa capa de interfaz, pasó a poder gobernar cualquier motor que la implemente, y de ahí que hoy Kubernetes no dependa de Docker.

Reparto que se pregunta: la OCI dice cómo son el contenedor, la imagen y el repositorio; la CRI dice cómo le habla Kubernetes al motor. Una es de la Linux Foundation y la otra es de Kubernetes.

Para el examen

  • Sus tres especificaciones: runtime, image y distribution

  • Qué permite: que las imágenes no queden atadas a un solo producto