Docker empaqueta una aplicación junto con todo lo que necesita para funcionar —el código, sus dependencias, sus librerías, su configuración— en una unidad que corre igual en cualquier máquina. Así desaparece el clásico «en mi computadora funciona»: si funciona en el contenedor, funciona en todos lados. Hay que distinguir dos cosas. Una imagen es una plantilla inmóvil, de solo lectura, con la aplicación y su entorno; es como una receta o un molde. Un contenedor es una instancia en ejecución de esa imagen; de una imagen se arrancan muchos contenedores iguales. La imagen se construye con un Dockerfile, un archivo de texto con los pasos para armarla. Y como un contenedor es efímero —al borrarlo se pierde lo que tenía dentro—, los datos que deben sobrevivir (una base de datos, archivos subidos) se guardan en volúmenes, un almacenamiento que vive fuera del contenedor. Docker no es una máquina virtual: comparte el núcleo del sistema, así que es mucho más liviano y rápido. Es la base de casi todo el DevOps moderno, incluida la orquestación.
Ver índice de contenidos
Qué problema resuelve Docker
Durante años, llevar una aplicación de la máquina del desarrollador al servidor era una fuente constante de problemas: versiones distintas de un lenguaje, una librería que faltaba, una variable de configuración diferente. El resultado era la frase temida: «en mi máquina funciona». El problema no era el código, sino el entorno donde corría.
La idea de empaquetar el entorno
Docker resuelve esto empaquetando la aplicación junto con su entorno completo: el sistema base, las dependencias, las librerías, la configuración, todo dentro de una unidad. Esa unidad corre igual en la laptop del desarrollador, en el servidor de pruebas y en producción, porque lleva su entorno consigo. Se acabó el «en mi máquina funciona»: la máquina viaja con la aplicación.
Una aclaración importante: Docker no es una máquina virtual. Una máquina virtual emula un sistema operativo entero, con su propio núcleo, lo que la hace pesada y lenta de arrancar. Un contenedor comparte el núcleo del sistema anfitrión y solo aísla la aplicación, por lo que ocupa mucho menos, arranca en segundos y permite correr decenas en una máquina que apenas sostendría unas pocas máquinas virtuales.
Imagen y contenedor
La confusión más común al empezar es entre imagen y contenedor. La analogía que lo aclara viene de la programación orientada a objetos: la imagen es como una clase (la plantilla) y el contenedor es como un objeto (la instancia creada a partir de esa plantilla).
- Una imagen es inmóvil y de solo lectura: contiene la aplicación y su entorno, pero no corre por sí sola. Se descarga de un registro (como Docker Hub) o se construye a partir de un Dockerfile.
- Un contenedor es una imagen en ejecución. De una misma imagen se arrancan muchos contenedores idénticos y aislados entre sí, lo que hace trivial escalar una aplicación corriendo más copias.
# Descargar una imagen y correr un contenedor a partir de ella
docker pull nginx
docker run -d -p 8080:80 nginx # -d en segundo plano, -p mapea puertos
# Ver los contenedores en ejecución
docker psEl Dockerfile
Para empaquetar tu aplicación necesitás construir tu propia imagen, y eso se hace con un Dockerfile: un archivo de texto con la receta, paso a paso, de cómo se arma. Cada instrucción crea una capa, y Docker las reutiliza si no cambiaron, lo que acelera las reconstrucciones.
# De qué imagen base partir
FROM node:20-alpine
# Carpeta de trabajo dentro del contenedor
WORKDIR /app
# Copiar e instalar dependencias primero (aprovecha la caché)
COPY package*.json ./
RUN npm ci --omit=dev
# Copiar el resto del código
COPY . .
# Qué comando corre al arrancar el contenedor
CMD ["node", "server.js"]Con ese archivo, docker build -t mi-app . construye la imagen, y docker run mi-app la corre. La imagen resultante lleva la aplicación y su entorno; se puede subir a un registro y desplegar en cualquier servidor. Un detalle de rendimiento y peso: partir de una imagen base pequeña (las variantes alpine) y copiar las dependencias antes que el código aprovecha la caché de capas.
Volúmenes: datos que sobreviven
Un contenedor es efímero: está pensado para crearse y destruirse con facilidad, y cuando se borra, todo lo que se escribió dentro de él desaparece. Eso es una ventaja para la aplicación —siempre arranca limpia— pero un desastre para los datos que deben persistir.
El contenido de una base de datos, los archivos que suben los usuarios, los registros que hay que conservar: todo eso va en un volumen, un almacenamiento gestionado por Docker que vive fuera del contenedor, en el sistema anfitrión. El contenedor lee y escribe en el volumen, pero los datos permanecen aunque el contenedor se elimine y se vuelva a crear. Guardar datos importantes dentro del contenedor es uno de los errores que más caro se pagan.
# Crear un volumen y montarlo en un contenedor de base de datos
docker volume create datos-db
docker run -d -v datos-db:/var/lib/postgresql/data postgresLa misma lógica separa la aplicación (sin estado, en la imagen) de los datos (con estado, en el volumen). Esa separación es la que permite luego actualizar la aplicación sin cortar el servicio y respaldar los datos por separado.
Errores frecuentes
- Confundir imagen con contenedor. La imagen es la plantilla de solo lectura; el contenedor, la instancia que corre.
- Guardar datos importantes dentro del contenedor. Al borrarlo se pierden; van en volúmenes.
- Escribir secretos en la imagen o el Dockerfile. Quedan grabados en las capas; van en variables de entorno.
- Imágenes enormes. Partir de bases pesadas o copiar todo sin filtrar hace imágenes lentas de mover; usar bases pequeñas y un
.dockerignore. - Correr todo como root dentro del contenedor. Conviene un usuario sin privilegios por seguridad.
- Meter varios servicios en un solo contenedor. La convención es un proceso por contenedor; para varios, se combinan con orquestación.
- Creer que Docker es una máquina virtual. Comparte el núcleo; es mucho más liviano y no aísla igual.
Preguntas frecuentes
¿Qué es Docker y para qué sirve?
Docker es una herramienta que empaqueta una aplicación junto con todo lo que necesita para funcionar —su código, sus dependencias, sus librerías y su configuración— en una unidad que corre de la misma manera en cualquier máquina. Sirve para eliminar el clásico problema de que un programa funcione en la computadora de quien lo desarrolló pero falle en el servidor por diferencias de entorno, resumido en la frase «en mi máquina funciona». Con Docker, la aplicación lleva su entorno consigo, así que si funciona dentro del contenedor funcionará igual en la laptop del desarrollador, en el entorno de pruebas y en producción. Esto simplifica enormemente el despliegue, hace reproducibles los entornos y es la base de gran parte de las prácticas modernas de DevOps, incluidas la integración continua, el despliegue automatizado y la orquestación de aplicaciones a gran escala con herramientas como Kubernetes.
¿Cuál es la diferencia entre una imagen y un contenedor?
Una imagen es una plantilla inmóvil y de solo lectura que contiene la aplicación con todo su entorno, pero que no corre por sí sola: es como una receta o un molde ya preparado. Un contenedor es una instancia en ejecución de esa imagen, es decir, la aplicación efectivamente corriendo. La analogía más clara viene de la programación orientada a objetos: la imagen es como una clase, que define cómo son las cosas, y el contenedor es como un objeto, una instancia concreta creada a partir de esa clase. De una misma imagen se pueden arrancar muchos contenedores idénticos y aislados entre sí, lo que hace muy sencillo escalar una aplicación simplemente corriendo más copias. Las imágenes se descargan de registros como Docker Hub o se construyen a partir de un Dockerfile, mientras que los contenedores se crean, arrancan, detienen y borran a partir de esas imágenes según haga falta.
¿Qué es un Dockerfile?
Es un archivo de texto que contiene la receta, paso a paso, para construir una imagen de Docker con tu propia aplicación. En él se indica de qué imagen base partir, qué dependencias instalar, qué archivos de código copiar dentro y qué comando debe ejecutarse cuando el contenedor arranque. Cada instrucción del Dockerfile genera una capa, y Docker reutiliza las capas que no cambiaron entre una construcción y otra, lo que acelera mucho las reconstrucciones cuando solo se modifica el código. A partir del Dockerfile, un comando de construcción arma la imagen, que luego puede subirse a un registro y desplegarse en cualquier servidor. Escribir bien el Dockerfile —partir de una imagen base pequeña, copiar las dependencias antes que el código para aprovechar la caché y no incluir archivos innecesarios— influye directamente en el tamaño de la imagen y en la velocidad tanto de construcción como de despliegue.
¿Por qué necesito volúmenes si el contenedor ya guarda datos?
Porque un contenedor es efímero por diseño: está pensado para crearse y destruirse con facilidad, y cuando se borra, todo lo que se escribió dentro de él se pierde. Eso es una ventaja para la aplicación, que siempre arranca en un estado limpio y conocido, pero sería un desastre para los datos que deben conservarse, como el contenido de una base de datos, los archivos que suben los usuarios o los registros históricos. Los volúmenes resuelven esto: son un almacenamiento gestionado por Docker que vive fuera del contenedor, en el sistema anfitrión, y que se conecta al contenedor para que este lea y escriba ahí. Así, los datos permanecen aunque el contenedor se elimine y se vuelva a crear, por ejemplo al actualizar la aplicación a una versión nueva. Esta separación entre la aplicación sin estado y los datos con estado es fundamental, porque es lo que permite actualizar o reemplazar contenedores sin perder información.
¿Docker es lo mismo que una máquina virtual?
No, y confundirlos es un malentendido habitual. Una máquina virtual emula un sistema operativo completo, con su propio núcleo corriendo sobre el sistema anfitrión, lo que la hace relativamente pesada en consumo de recursos y lenta de arrancar, aunque ofrece un aislamiento muy fuerte. Un contenedor de Docker, en cambio, no emula un sistema operativo entero: comparte el núcleo del sistema anfitrión y solo aísla la aplicación y su entorno inmediato. Como consecuencia, un contenedor ocupa mucho menos espacio, arranca en segundos y permite correr decenas de ellos en una máquina que apenas sostendría unas pocas máquinas virtuales. La contrapartida es que el aislamiento es menor y que todos los contenedores comparten el mismo núcleo, lo que hay que tener en cuenta en escenarios donde la separación estricta es un requisito de seguridad. En la práctica, ambas tecnologías conviven y muchas veces los contenedores corren dentro de máquinas virtuales.
¿Dónde guardo las contraseñas y claves que usa mi contenedor?
En variables de entorno que se pasan al contenedor al ejecutarlo, o mediante un mecanismo de gestión de secretos, pero nunca escritas dentro de la imagen ni en el Dockerfile. La razón es que todo lo que se incluye en la imagen queda grabado de forma permanente en sus capas, y esas capas se pueden inspeccionar, de modo que un secreto escrito ahí queda expuesto a cualquiera que tenga acceso a la imagen, incluso si se «borra» en un paso posterior, porque la capa anterior sigue existiendo. Lo correcto es mantener la imagen genérica y sin credenciales, e inyectar los secretos en el momento de ejecutar el contenedor a través de variables de entorno o de un sistema de gestión de secretos, que además permite usar credenciales distintas en desarrollo, pruebas y producción con la misma imagen. Esta es exactamente la misma regla que se aplica al código fuente y a los pipelines: los secretos viven en un mecanismo aparte pensado para protegerlos, no dentro de lo que se versiona o se distribuye.
Fuentes
Documentación oficial y material de la comunidad consultados para esta guía. Fecha de consulta: 28 de julio de 2026.
Aportes de la comunidad Underc0de
- Underc0de, foro. Sección GNU/Linux. Consultas sobre contenedores, servidores y despliegue.
- Underc0de, foro. Sección Programación. Empaquetado y entrega de aplicaciones.
Documentación oficial
- Docker. Get started. La introducción oficial a imágenes y contenedores.
- Docker. Dockerfile reference. Todas las instrucciones para construir una imagen.
- Docker. Volumes. Cómo persistir datos fuera del contenedor.
- Open Container Initiative. OCI. El estándar abierto de imágenes y runtime de contenedores.