Una imagen Docker es una plantilla inmutable, de solo lectura, que contiene un sistema de archivos con todo lo necesario para ejecutar una aplicación (código, dependencias, configuración). Un contenedor es una instancia en ejecución de esa imagen, con una capa de escritura propia. La analogía más útil es la de la programación orientada a objetos: la imagen es la clase y el contenedor es el objeto. De una misma imagen puedes arrancar tantos contenedores como quieras, cada uno aislado de los demás.
Si acabas de empezar con Docker, esta distinción es la que evita la mayoría de confusiones: qué se descarga, qué se ejecuta, qué ocupa espacio y qué se pierde al borrar.
Qué es una imagen
Una imagen se construye por capas. Cada instrucción de un Dockerfile (FROM, RUN, COPY…) genera una capa, y las capas se apilan: la de abajo suele ser un sistema base (Debian, Alpine, Ubuntu), encima van las dependencias y arriba el código de tu aplicación. Las capas son de solo lectura y se comparten entre imágenes: si diez imágenes parten de la misma base, esa base ocupa espacio en disco una sola vez.
Las imágenes se identifican por nombre y etiqueta (node:22-alpine, nginx:1.27) y se distribuyen a través de registros como Docker Hub.
# Descargar una imagen
docker pull nginx:1.27
# Listar imágenes locales
docker images
# Construir una imagen a partir del Dockerfile del directorio actual
docker build -t mi-app:1.0 .
# Eliminar una imagen (solo si ningún contenedor la usa)
docker rmi mi-app:1.0
Qué es un contenedor
Un contenedor es un proceso (o grupo de procesos) que se ejecuta aislado del resto del sistema, usando la imagen como sistema de archivos base y añadiendo encima una capa de escritura. Todo lo que la aplicación escribe mientras se ejecuta (logs, archivos temporales, datos) va a esa capa. Cuando el contenedor se elimina, la capa de escritura desaparece con él; la imagen queda intacta.
# Crear y arrancar un contenedor a partir de una imagen
docker run -d --name web -p 8080:80 nginx:1.27
# Listar contenedores en ejecución (-a incluye los detenidos)
docker ps
docker ps -a
# Ver logs y entrar en el contenedor
docker logs web
docker exec -it web sh
# Detener, arrancar de nuevo y eliminar
docker stop web
docker start web
docker rm web
docker run hace dos cosas a la vez: crea el contenedor (docker create) y lo arranca (docker start). Por eso, si ejecutas docker run tres veces con la misma imagen, obtienes tres contenedores distintos, no uno.
La relación entre ambos, en una tabla
| Imagen | Contenedor | |
|---|---|---|
| Qué es | Plantilla de solo lectura | Instancia en ejecución (o detenida) de una imagen |
| Se crea con | docker build, docker pull |
docker run, docker create |
| Se lista con | docker images |
docker ps -a |
| Se elimina con | docker rmi |
docker rm |
| ¿Cambia al ejecutarse? | No | Sí, en su capa de escritura |
| ¿Cuántos puede haber? | Una por nombre:etiqueta | Tantos como quieras por imagen |
Dónde se guardan los datos: volúmenes
Como la capa de escritura muere con el contenedor, cualquier dato que deba sobrevivir (una base de datos, archivos subidos por usuarios) tiene que vivir fuera, en un volumen o en un directorio del host montado en el contenedor:
# Volumen gestionado por Docker
docker run -d --name db -v datos-db:/var/lib/postgresql/data postgres:16
# Directorio del host (bind mount), útil en desarrollo
docker run -d --name web -v "$(pwd)/html:/usr/share/nginx/html:ro" -p 8080:80 nginx:1.27
Con esto puedes eliminar y recrear el contenedor sin perder los datos. La documentación sobre volúmenes detalla las diferencias entre ambas opciones.
Errores habituales
- Pensar que
docker stoplibera el espacio. Un contenedor detenido sigue existiendo con su capa de escritura. Para liberar espacio hay que eliminarlo condocker rm(o usardocker run --rmpara que se borre solo al terminar). - Guardar datos dentro del contenedor. Funciona hasta que lo recreas. Usa volúmenes desde el principio.
- Modificar un contenedor y esperar que la imagen cambie. No ocurre. Si necesitas que un cambio forme parte de la imagen, modifícalo en el
Dockerfiley vuelve a construir.docker commitexiste, pero produce imágenes no reproducibles y conviene evitarlo. - Acumular imágenes y contenedores huérfanos.
docker system dfmuestra cuánto ocupan;docker system pruneelimina contenedores detenidos, redes sin uso e imágenes colgantes (pide confirmación). - Usar la etiqueta
latesten producción.latestcambia con el tiempo; fija una versión concreta (node:22.12-alpine) para que el despliegue sea reproducible.
Conclusión
La imagen es la plantilla; el contenedor, la ejecución. Las imágenes se construyen y descargan, los contenedores se arrancan, detienen y eliminan, y los datos que deben durar van en volúmenes. Con esos tres conceptos claros, el resto de Docker (redes, Compose, registros) se entiende como combinaciones de lo mismo.