Docker permite empaquetar una aplicación como una imagen inmutable y ejecutarla como un , es decir, como uno o varios procesos aislados que comparten el kernel del host.
contenedor
La diferencia importante no está solamente en “meter una app en una caja”. Docker intenta convertir la preparación del entorno en un proceso repetible:
Texto
código fuente
+ dependencias
+ instrucciones de construcción
→ imagen versionada
→ contenedor configurado
→ proceso ejecutándose
Una imagen responde principalmente qué debe ejecutarse. El contenedor representa una instancia concreta en ejecución, con variables, red, mounts, límites y permisos propios.
Antes de usar contenedores, una aplicación suele depender de preparación manual:
instalar una versión específica del runtime;
instalar librerías del sistema;
crear directorios y usuarios;
definir variables de entorno;
copiar archivos al lugar correcto;
configurar puertos y permisos;
repetir el procedimiento en cada equipo o servidor.
Ese proceso produce variación. Dos máquinas que parecen iguales pueden tener versiones distintas, archivos residuales o configuraciones no documentadas. El conocido “funciona en mi máquina” normalmente significa que la aplicación depende de características del entorno que nunca fueron declaradas.
Docker no elimina todas las diferencias, pero mueve una parte importante de ellas hacia artefactos y configuración explícita. El Dockerfile documenta la construcción; la imagen conserva el resultado; el runtime define cómo se ejecuta.
Los tres contenedores pueden compartir las capas de la misma imagen, pero cada uno tiene:
identidad y lifecycle propios;
proceso principal diferente o argumentos diferentes;
variables de entorno propias;
una capa writable separada;
conexiones de red propias;
mounts y límites propios.
Modificar un contenedor no modifica automáticamente la imagen. Cuando ese contenedor se elimina, los cambios realizados en su capa writable desaparecen, salvo que se hayan guardado en un volume o en un servicio externo.
Un contenedor Linux no es una máquina virtual pequeña. Es un conjunto de procesos normales del host a los que el kernel presenta una vista aislada de ciertos recursos.
Los cgroups contabilizan y limitan recursos como CPU, memoria y cantidad de procesos. El aislamiento no implica automáticamente límites: un contenedor sin restricciones puede competir por gran parte de la capacidad del host.
La imagen aporta capas read-only. Encima se añade una capa writable específica del contenedor. Volumes y bind mounts pueden reemplazar rutas concretas del filesystem visible.
Linux divide muchos privilegios de root en capabilities. Docker puede eliminar capacidades, aplicar seccomp y trabajar con AppArmor o SELinux. Estas medidas reducen lo que un proceso comprometido puede hacer, pero no convierten el contenedor en una frontera absoluta.
La API y PostgreSQL se ejecutan como contenedores diferentes porque tienen lifecycle, dependencias y responsabilidades distintas. La base de datos usa un volume porque sus datos deben sobrevivir al reemplazo del contenedor.
La API no conecta a localhost:5432: dentro del contenedor, localhost significa el propio contenedor. Se conecta al nombre DNS del servicio, por ejemplo db.
El contenedor también termina. Esto puede ocurrir por configuración inválida, archivos faltantes o porque se lanzó una tarea que finaliza en lugar de un servidor persistente.
Root dentro del contenedor no siempre equivale a root sin restricciones en el host, pero aumenta el impacto potencial. Debe usarse un usuario no privilegiado salvo necesidad justificada.
Normalmente no. Los contenedores Linux comparten el kernel del host. Docker Desktop utiliza una VM Linux en macOS y Windows para disponer de ese kernel.
No necesariamente. Mounts peligrosos, capabilities excesivas, --privileged, acceso al Docker socket o vulnerabilidades del kernel pueden ampliar el riesgo.
El segundo contenedor no encuentra el archivo porque cada instancia tiene su propia writable layer. Luego repite usando un volume para observar la diferencia.