Qué es Docker realmente (y qué NO es)
Introducción
Docker es una de las tecnologías más mencionadas en el desarrollo moderno: entrevistas, ofertas, proyectos, cursos… Y a la vez es una de las más malinterpretadas.
Se vende como “una máquina virtual”, “un servidor mágico” o incluso “seguridad por defecto”. Ninguna de esas frases es correcta. Docker es potente, sí. Pero solo cuando se entiende qué hace y qué NO hace.
En este post lo explicamos como toca: definición útil, cómo funciona, casos de uso reales, límites, errores comunes, y buenas prácticas operativas para producción.
Mini guía en 10 minutos: lo que deberías entender sí o sí
- Docker empaqueta tu aplicación y dependencias en una imagen reproducible.
- Un contenedor es una imagen en ejecución (un proceso aislado, no una VM).
- El estado NO vive en el contenedor: si hay estado, va en volúmenes o servicios externos.
- Docker no es seguridad: si lo despliegas mal, el contenedor es igual de inseguro.
- Docker Compose es el 80/20 para desarrollo y entornos simples.
Qué es Docker (definición útil y realista)
Docker es una plataforma para construir, empaquetar y ejecutar software en contenedores reproducibles. Un contenedor ejecuta tu aplicación en un entorno controlado, garantizando que binarios, librerías y configuración sean consistentes entre dev, test y producción.
En una frase: Docker reduce el “en mi máquina funciona” convirtiendo el entorno en un artefacto versionable.
Qué es un contenedor (realmente)
Un contenedor es un proceso aislado que usa el kernel del host, pero tiene su propio filesystem (capas), red y límites (cuando se configuran).
- Arranca en segundos.
- Consume menos recursos que una VM.
- Es fácil de crear/destruir (ideal para CI/CD).
- Su aislamiento es “ligero”: útil, pero no equivalente a una VM bien configurada.
Docker vs máquinas virtuales (sin simplismos)
| Aspecto | Máquina virtual | Contenedor |
|---|---|---|
| Sistema operativo | Completo por VM | Comparte kernel con el host |
| Arranque | Más lento | Muy rápido |
| Consumo | Mayor | Menor |
| Aislamiento | Más fuerte | Más ligero (suficiente en muchos casos) |
| Uso típico | Infra base / aislamiento fuerte | Apps y servicios, despliegues repetibles |
Docker no sustituye a las VMs. De hecho, muchas veces Docker vive dentro de una VM. Son capas distintas y resuelven problemas distintos.
Qué NO es Docker (conviene repetirlo)
- No es una VM (aunque “se parezca” por fuera).
- No es un servidor: necesitas infraestructura (host, red, storage, DNS…).
- No es un orquestador: eso es Kubernetes/Nomad/Swarm (y no siempre lo necesitas).
- No es un escudo de seguridad: hardening y controles siguen siendo necesarios.
Los 3 conceptos que se mezclan (y deberían estar claros)
- Dockerfile: receta para construir la imagen. Es código. Se revisa. Se versiona.
- Imagen: plantilla inmutable con app + dependencias. Se versiona con tags.
- Contenedor: instancia en ejecución de una imagen (proceso).
Casos de uso reales donde Docker aporta muchísimo
1) Desarrollo local consistente (equipo real)
Equipo con diferentes sistemas operativos, versiones y dependencias. Docker/Compose reduce fricción: bases de datos, caches, colas, etc. iguales para todos.
2) CI/CD limpio (builds reproducibles)
El pipeline no necesita “tener instalado medio internet”. Ejecutas build/tests en contenedores versionados. Resultado: menos flakiness y menos “depende del runner”.
3) Despliegues predecibles
“La misma imagen” se promueve entre entornos. Cambia la configuración, no el binario. Eso reduce sorpresas.
4) Arquitectura por servicios (sin volverte loco)
Incluso sin microservicios, es habitual separar: app + DB + cache + reverse proxy. Docker lo hace operable.
Cuándo Docker NO compensa
- Scripts pequeños o herramientas locales sin dependencias.
- Apps triviales con runtime homogéneo y estable.
- Equipos que no pueden mantener imágenes (parches, CVEs, lifecycle) y lo dejarán abandonado.
Docker Compose: el punto de entrada más útil
Compose no es “para principiantes”, es una herramienta práctica para entornos simples. Define servicios, redes y volúmenes en un fichero, y levanta todo con un comando.
Mini ejemplo conceptual: aplicación + base de datos + cache
La idea (sin depender de sintaxis exacta) es: tres servicios, una red interna, un volumen para persistencia y variables por entorno. Eso elimina “instálate X y configúralo”.
Docker en producción: lo que marca la diferencia
Docker aporta reproducibilidad, no “seguridad automática”. En producción la pregunta no es “¿arranca?”, sino “¿se opera y se recupera cuando falla?”.
Buenas prácticas no negociables
- Artefacto único: construye una imagen y promuévela entre entornos (no recompiles por entorno).
- Versionado real: evita
latestcomo verdad; usa tags semánticos o commit SHA. - Secretos fuera: nunca en repo, nunca en imagen, nunca en build args.
- Permisos mínimos: usuario no-root cuando sea viable, y nada de
--privileged“por si acaso”. - Observabilidad: logs estructurados + healthchecks + métricas mínimas (latencia/errores).
Tabla rápida: riesgo → control
| Riesgo | Cómo se manifiesta | Control recomendado |
|---|---|---|
| Imagen vulnerable | CVE en base image/dependencias | Escaneo en CI (Trivy/Grype) + actualización periódica |
| Secretos filtrados | Tokens en repo/imagen | Gitleaks + gestión de secretos (Vault/KMS/secret manager) |
| Contenedor “root” | Impacto mayor ante exploit | Usuario no-root + permisos mínimos |
| Estado dentro del contenedor | Pérdida de datos al reiniciar | Volúmenes o servicios externos (DB/Storage) |
| Caídas silenciosas | No sabes qué pasó | Healthchecks + logs + alertas básicas |
Malas prácticas extendidas (y por qué salen caras)
- “latest” + sin escaneo → degradación silenciosa: un día entra una CVE crítica y no te enteras.
- “--privileged por comodidad” → conviertes un contenedor en un riesgo operativo serio.
- Logs solo en consola sin correlación → MTTR alto: “me enteré por el cliente”.
Checklist pre-producción (1 minuto)
- ¿La imagen está versionada (no
latest) y es reproducible? - ¿No hay secretos en repo/imagen?
- ¿Corre con permisos mínimos (no-root si aplica)?
- ¿El estado está fuera del contenedor?
- ¿Hay healthcheck y logs útiles para diagnosticar?
- ¿Se escanea la imagen en CI?
Herramientas útiles para trabajar “pro” con Docker
- Inspección: herramientas tipo “dive” ayudan a entender capas y tamaño (sin obsesión).
- Escaneo: Trivy para CVEs y misconfigurations; Syft/Grype para SBOM y vulnerabilidades.
- Secretos: Gitleaks para evitar llaves en repo.
- Dockerfile: linters tipo Hadolint para buenas prácticas (sin convertirlo en dogma).
Errores comunes (los que se pagan caros)
- Meter todo en un contenedor (DB + app + cron + proxy) “porque es más fácil”. No lo es a medio plazo.
- Guardar estado dentro del contenedor. Luego reinicias y pierdes cosas.
- Imágenes gigantes (herramientas de build en runtime, caches, basura).
- Confundir Docker con arquitectura. Docker empaqueta, no diseña por ti.
- “Funciona” sin controles. Y el día que falla, no hay plan de diagnóstico.
Conclusión
Docker no es una moda ni una bala de plata. Es una herramienta potente si se usa con criterio: reproducibilidad, portabilidad, CI/CD y despliegues predecibles.
Pero si se adopta sin entender límites (estado, seguridad, configuración, operación), se convierte en otra fuente de problemas.
En Gondor apostamos por Docker como parte de una arquitectura consciente: cada pieza existe porque resuelve un problema real, no porque “todo el mundo la usa”.