Desarrollo web

Docker: diferencia entre imagen y contenedor explicada con comandos

Qué es una imagen Docker, qué es un contenedor y cómo se relacionan, con los comandos básicos para crear, listar y eliminar cada uno y los errores más frecuentes.

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

  1. Pensar que docker stop libera el espacio. Un contenedor detenido sigue existiendo con su capa de escritura. Para liberar espacio hay que eliminarlo con docker rm (o usar docker run --rm para que se borre solo al terminar).
  2. Guardar datos dentro del contenedor. Funciona hasta que lo recreas. Usa volúmenes desde el principio.
  3. 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 Dockerfile y vuelve a construir. docker commit existe, pero produce imágenes no reproducibles y conviene evitarlo.
  4. Acumular imágenes y contenedores huérfanos. docker system df muestra cuánto ocupan; docker system prune elimina contenedores detenidos, redes sin uso e imágenes colgantes (pide confirmación).
  5. Usar la etiqueta latest en producción. latest cambia 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.

Fuentes y referencias

  1. Docker Docs: What is an image? docs.docker.com
  2. Docker Docs: What is a container? docs.docker.com
  3. Docker Docs: docker container run docs.docker.com
  4. Docker Docs: Dockerfile reference docs.docker.com
  5. Docker Docs: Volumes docs.docker.com
Artículos de Desarrollo web