Virtualización y Containerización
En la Unidad 1 vimos qué es "la nube" como modelo. En esta unidad bajamos un nivel: ¿cómo hace técnicamente un proveedor para que muchos clientes compartan un mismo servidor físico sin pisarse? La respuesta tiene dos capas, una sobre la otra: virtualización y containerización.
1. La idea de fondo
Una computadora física es cara, ocupa espacio y consume energía. Si en cada servidor corre una sola aplicación, la mayoría del tiempo está al 10 % de uso: pagamos por capacidad que no usamos. Las dos tecnologías de esta unidad resuelven el mismo problema desde ángulos distintos: aislar varias cargas dentro de un mismo hardware para aprovecharlo bien.
Aislamiento sin desperdicio: la clave del cómputo moderno.
La idea de fondo
Tanto las máquinas virtuales como los contenedores resuelven el mismo dilema: ¿cómo hago que varias cargas convivan en una sola máquina física sin que se molesten? La diferencia está en qué nivel de la pila se virtualiza.
Dos capas, dos abstracciones
VirtualizaciónSimula hardware completo: cada VM tiene su propio sistema operativo.
ContainerizaciónComparte el sistema operativo del host: cada contenedor es solo un proceso aislado.
Para tener en cuenta
- No es "VM vs contenedor": en la nube real conviven y se complementan.
- Los contenedores ganaron protagonismo porque son livianos, rápidos y portables.
2. Virtualización
La idea de virtualización es vieja: ya estaba en los mainframes de IBM de los años 60-70 (CP/CMS, VM/370), donde se usaba para tiempo compartido entre usuarios. Lo que apareció en los 2000 fue la virtualización x86 mainstream (VMware ESX en 2001, Xen en 2003, KVM en 2007), que llevó esa idea al hardware de commodity y fue la primera respuesta seria al problema del desperdicio en servidores comunes. Permite ejecutar varios sistemas operativos completos sobre un mismo hardware, cada uno dentro de una "máquina virtual" (VM).
Emulación completa de una computadora dentro de otra. Tiene su propio sistema operativo, su propia memoria, su propio disco virtual y su propia tarjeta de red virtual. Para las aplicaciones que corren adentro, es indistinguible de un servidor físico.
Metáfora
Como dividir una casa grande en varios departamentos independientes, cada uno con su propia cocina, baño y entrada. Comparten la estructura del edificio pero internamente son autónomos.
Según la nube
Cuándo conviene usarlas
- Necesitás un sistema operativo distinto al del host (Windows sobre Linux, etc.).
- La aplicación tiene requisitos específicos de kernel o drivers.
- Necesitás aislamiento fuerte por motivos de seguridad o compliance.
El software que crea, ejecuta y administra las máquinas virtuales. Reparte CPU, memoria, disco y red entre las VMs y se asegura de que ninguna invada el espacio de otra.
Metáfora
El portero del edificio: controla quién entra, quién usa el ascensor y cuánta luz consume cada departamento.
Ejemplos comunes
Dato útil
- Los grandes proveedores de nube usan hypervisores propios optimizados (ej. AWS usa Nitro, basado en KVM).
Hypervisor Tipo 1 vs Tipo 2
Tipo 1 (bare-metal)
- Corre directamente sobre el hardware, sin SO huésped.
- Más rápido y eficiente: ideal para data centers.
- Más complejo de instalar y operar.
- Ejemplos: ESXi, Hyper-V, Xen, KVM.
Tipo 2 (hosted)
- Corre como una aplicación dentro de un SO normal.
- Fácil de instalar en tu laptop para pruebas.
- Menos eficiente: hay un SO en el medio.
- Ejemplos: VirtualBox, VMware Workstation, Parallels.
3. Containerización
Las VMs resuelven el problema del aislamiento, pero arrastran un costo: cada una lleva un sistema operativo entero adentro. Si necesitás 50 VMs para 50 microservicios, tenés 50 kernels corriendo en paralelo. Mucho desperdicio de RAM y disco. La containerización es la siguiente vuelta de tuerca: aprovecha que el sistema operativo ya está corriendo y aísla solamente los procesos.
Un proceso (o grupo de procesos) que corre sobre el kernel del sistema operativo del host, pero con su propio sistema de archivos, su propia red y sus propios límites de recursos. No tiene sistema operativo propio: comparte el del host.
Metáfora
Como un local en un shopping: usás la estructura, electricidad y aire acondicionado del edificio (kernel del host), pero adentro decorás y vendés lo que vos quieras, sin ver a los locales vecinos.
Tecnologías populares
Ventajas frente a una VM
- Arranque en milisegundos (vs minutos de una VM).
- Imagen liviana: decenas de MB vs gigabytes.
- Reproducible: la misma imagen corre igual en tu laptop, en CI y en producción.
El "molde" desde el que se levanta un contenedor: un paquete inmutable que contiene el código de la aplicación, sus dependencias, librerías del sistema mínimas y metadatos (variables de entorno, comando de arranque, puertos expuestos). Se guarda en un registry.
Metáfora
La imagen es la receta y el contenedor es el plato cocinado: con una receta podés cocinar cuantos platos quieras, y todos salen iguales.
Conceptos relacionados
- Registry: servidor donde se guardan imágenes (Docker Hub, GitHub Container Registry, AWS ECR).
- Tag: versión de una imagen (
nginx:1.27,postgres:16-alpine). - Layer: cada instrucción del Dockerfile genera una capa cacheable; las imágenes son la suma de capas.
4. VM vs Contenedor
La pregunta "VM o contenedor" no tiene una respuesta única: depende del aislamiento, la portabilidad y la velocidad que necesites.
Máquina virtual vs Contenedor
Máquina virtual
- Aislamiento fuerte (kernel propio).
- Puede correr cualquier SO.
- Arranque en minutos.
- Pesada (GB de disco, mucha RAM).
Contenedor
- Liviano (MB de disco, poca RAM).
- Arranque en milisegundos.
- Comparte kernel con el host (menor aislamiento).
- Atado al SO del host (un contenedor Linux no corre en Windows nativo).
5. Docker, el estándar de facto
Docker no inventó los contenedores —la tecnología venía desde los 2000 con cgroups y namespaces en Linux— pero los hizo accesibles a todo el mundo en 2013 con un CLI simple, un formato de imagen estándar y un registry público. Hoy es prácticamente sinónimo de "contenedor" en el día a día. Para el panorama completo de productos gestionados por proveedor (ECS, GKE, Cloud Run, Container Apps, Fly.io y el resto) y cuándo conviene cada uno, ver el recurso containers.
Docker es un conjunto de herramientas para construir, distribuir y ejecutar
contenedores. Tiene tres componentes principales: el daemon
(servicio en segundo plano que ejecuta los contenedores), el
CLI (el cliente que usás vos para darle órdenes) y el
registry (Docker Hub u otros, donde se publican las
imágenes). La pieza más importante para el desarrollador es el
Dockerfile: un archivo de texto que describe paso a paso
cómo construir una imagen. A partir de él, docker build
produce la imagen, docker run levanta un contenedor desde
ella, y docker push / pull la sube o baja de un registry.
- Creá un archivo llamado
Dockerfileen la raíz de tu app. - Empezá con una imagen base (
FROM node:20-alpine,FROM php:8.4-cli, etc.). - Copiá tu código adentro con
COPY . /app. - Instalá dependencias (
RUN composer install,RUN npm ci). - Definí el comando de arranque con
CMD ["php", "-S", "0.0.0.0:8000"]. - Construí la imagen:
docker build -t mi-app:1.0 . - Probá localmente:
docker run -p 8000:8000 mi-app:1.0 - Autenticate contra el registry:
docker login(Docker Hub) odocker login ghcr.iopara GitHub. - Subila al registry:
docker push mi-usuario/mi-app:1.0
# Ver contenedores corriendo
docker ps
# Ver TODOS los contenedores (incluso los detenidos)
docker ps -a
# Entrar a un contenedor con shell
docker exec -it <container_id> sh
# Ver logs en vivo
docker logs -f <container_id>
# Detener y eliminar un contenedor
docker stop <container_id> && docker rm <container_id>
# Limpiar imágenes, contenedores y volúmenes sin usar
docker system prune -a --volumes
Tip: en muchos comandos podés usar los primeros 3–4 caracteres del ID en lugar de pegarlo entero.
6. Persistencia y red
Por defecto, los contenedores son efímeros: cuando se eliminan, sus datos se pierden. Y están aislados de la red del host. Para apps reales necesitamos dos cosas: una forma de persistir datos y una forma de comunicar contenedores entre sí.
Para resolver la persistencia, Docker provee volúmenes:
espacios de almacenamiento gestionados por el motor que sobreviven al
ciclo de vida del contenedor. Se montan dentro de uno o varios
contenedores y los datos escritos ahí persisten aunque el contenedor se
elimine. Hay tres tipos: named volumes, gestionados por Docker y
recomendados para datos de aplicaciones; bind mounts, que mapean
un directorio del host directamente al contenedor (útil en desarrollo);
y tmpfs, almacenamiento en RAM que se pierde al reiniciar.
Un ejemplo típico: docker run -v miapp_datos:/var/lib/postgresql/data postgres:16.
Para resolver la comunicación entre contenedores, Docker crea
redes virtuales. Dentro de una misma red, cada contenedor
"ve" a los demás por su nombre de servicio en vez de por IP. Las redes
típicas son: bridge (default, red privada entre contenedores
del mismo host), host (sin aislamiento, comparte la red del
host), overlay (distribuida entre múltiples hosts, usada por
Swarm y Kubernetes) y none (aislamiento total sin red).
Así, si tu aplicación se llama web y la base se llama
db, podés conectarte desde la app a
postgres://db:5432 y Docker resuelve el nombre internamente.
7. Orquestación: cuando un solo host no alcanza
Con Docker corriendo en una máquina solucionás el "desarrollo local" y los despliegues simples. Pero en producción real necesitás varios hosts, balanceo de carga, reinicios automáticos, despliegues sin interrupción y escalado horizontal. Esa capa se llama orquestación. Una alternativa para evitar parte de esa complejidad cuando el caso de uso es event-driven y la carga es esporádica es ir directo a serverless: el proveedor decide dónde y cuándo correr tu código y vos no operás cluster.
Orquestar contenedores: del "una máquina, una app" al "muchas máquinas, una plataforma".
Qué problema resuelve
Una vez que tu aplicación tiene 5, 20 o 200 contenedores corriendo en un cluster, hace falta una pieza que decida en qué máquina arranca cada uno, reinicie los que mueren, escale los que reciben carga y los reemplace en orden al actualizar.
Capacidades típicas
SchedulingAsigna contenedores a hosts del cluster según recursos disponibles.
Self-healingReinicia o reemplaza contenedores que fallan.
Service discoveryDa nombres estables a servicios que cambian de IP.
Rolling updatesDespliega versiones nuevas sin downtime.
Para tener en cuenta
- No todos los proyectos necesitan orquestación: arrancar con un solo host y Docker Compose es perfectamente válido.
- La complejidad operativa de Kubernetes es real: tiene curva de aprendizaje empinada.
Sistema open-source desarrollado originalmente por Google, hoy mantenido por la CNCF. Es la herramienta dominante para correr contenedores en producción a escala. Maneja clusters de cientos o miles de nodos.
Conceptos básicos
- Pod: unidad mínima — uno o varios contenedores que comparten red y volúmenes.
- Deployment: declarás cuántas réplicas querés; k8s mantiene ese número.
- Service: punto de entrada estable a un conjunto de Pods.
- Ingress: regla de enrutamiento HTTP desde el exterior.
- ConfigMap / Secret: configuración y credenciales separadas del código.
Para escenarios más simples existe Docker Compose, una
herramienta de Docker para definir aplicaciones multi-contenedor en un
solo archivo YAML (compose.yaml) y levantarlas con un
comando. No reemplaza a Kubernetes, pero es el "punto dulce" para
desarrollo local, demos y producciones chicas. Un compose.yaml
típico define un servicio web (tu app), un servicio
db (Postgres) y un volumen para la base; con
docker compose up -d levanta todo configurado y conectado.
Es exactamente lo que usa este mismo proyecto Sidecar.
Docker Compose vs Kubernetes
Docker Compose
- Curva de aprendizaje plana: un archivo YAML simple.
- Perfecto para desarrollo local y CI.
- Limitado a un solo host (sin balanceo multi-nodo).
- Sin self-healing avanzado ni rolling updates.
Kubernetes
- Escala a cientos o miles de nodos.
- Self-healing, rolling updates, autoscaling.
- Curva de aprendizaje empinada.
- Costo operativo alto si lo gestionás vos mismo.
8. Errores comunes
:latest en producción
Qué suele pasar
El despliegue funciona hoy con nginx:latest; mañana sale una versión major nueva, :latest apunta a ella y tu producción se rompe sin que hayas tocado nada.
Por qué
:latest es una etiqueta mutable: lo que apunta hoy puede ser distinto mañana. Rompe la promesa de reproducibilidad de los contenedores.
Cómo evitarlo
Usá etiquetas específicas (nginx:1.27.3) o, todavía mejor, digests inmutables (nginx@sha256:abc...) en los manifiestos de producción.
Qué suele pasar
Levantás Postgres en un contenedor, cargás datos, todo funciona. Al actualizar la imagen recreás el contenedor y descubrís que perdiste todo.
Por qué
El sistema de archivos del contenedor es efímero: vive y muere con el contenedor. Sin un volumen montado, no hay persistencia real.
Cómo evitarlo
Para cualquier dato que tenga que sobrevivir, montá un volumen (-v o volumes: en compose) apuntando al directorio de datos del servicio.
Qué suele pasar
Tu app dentro del contenedor corre como root porque "es lo más simple". Una vulnerabilidad en la app permite a un atacante escapar del contenedor con privilegios totales.
Por qué
El aislamiento de los contenedores es de proceso, no completo. Si el proceso es root, en algunos escenarios puede aprovechar agujeros del kernel para afectar al host.
Cómo evitarlo
En el Dockerfile, creá un usuario sin privilegios y usá USER appuser antes del CMD. La mayoría de las imágenes oficiales modernas ya vienen así.
9. Tips y buenas prácticas
Usá multi-stage builds: tu imagen final no debería tener compiladores, paquetes de desarrollo ni código fuente. Compilá en una imagen "builder" pesada y copiá solo el binario / los artefactos compilados a una imagen final mínima (Alpine, Distroless).
Creá un .dockerignore con node_modules/, vendor/, .git/, archivos secretos. Sin él, COPY . . mete todo eso en la imagen, inflándola y exponiendo material que no debería viajar.
Configurá un healthcheck en tu Dockerfile (HEALTHCHECK) o en el compose (healthcheck:). Permite que el orquestador detecte cuándo el contenedor está "vivo pero no listo" y reaccione (reiniciar, sacar del balanceador).
10. Glosario rápido
nginx:1.27); evitar :latest en producción.
11. Para profundizar
Docker Inc. · lectura por temas
El "Get Started" oficial es la mejor forma de tener Docker andando en una tarde. Cubre instalación, primer Dockerfile, networking y volúmenes.
Ir al recursokubernetes.io · ~1 h de práctica
Recorrido guiado por los conceptos básicos de Kubernetes con un cluster sandbox en el navegador. Ideal para entender Pods, Deployments y Services sin instalar nada.
Ir al recursoAdam Wiggins · lectura ~30 min
Las 12 reglas que toda aplicación lista para contenerizar debería respetar (config por env vars, procesos sin estado, logs a stdout, etc.). Es un clásico breve y prácticamente obligatorio.
Ir al recursoDocker · sesiones de 4 h gratuitas
Terminal Docker en el navegador, sin instalar nada. Sirve para practicar comandos y experimentar con redes y clusters Swarm sin riesgo.
Ir al recurso12. Cierre
Virtualización y containerización son las dos capas técnicas que hacen posible la nube moderna.
Qué hay que llevarse
La nube no es magia: por debajo conviven hypervisores que multiplican hardware en VMs, y orquestadores que multiplican VMs en miles de contenedores efímeros. Entender estas dos abstracciones —y cuándo conviene cada una— es la base para diseñar cualquier sistema cloud-native.
Qué viene
Unidad 3Las tres leyes que rigen las arquitecturas distribuidas: Conway, Gall y CAP.
Unidad 4Metodologías ágiles y ciclo de vida del software.
Unidad 5IA generativa: vocabulario, RAG, los tres laboratorios y modelos de negocio.
Unidad 6Aplicaciones concretas: cómo se integran todas las piezas en un producto real.
Antes de seguir
- Asegurate de poder explicar en una frase la diferencia entre una VM y un contenedor.
- Probá levantar un servicio simple (nginx o postgres) con Docker en tu máquina.
- Hojeá el compose.yaml de este mismo proyecto (Sidecar): es un ejemplo real de Docker Compose en acción.