Ir al contenido

Laboratorio 04 - Ejecución de contenedores Docker

En este laboratorio trabajará con una aplicación web empaquetada como imagen Docker y recorrerá el ciclo de vida de un contenedor desde su creación hasta su eliminación.

La aplicación utilizada es Grocery List App, una aplicación para gestionar listas de compras disponible en Docker Hub. A partir de ella podrá relacionar los comandos fundamentales de Docker con los cambios que producen sobre una imagen, un contenedor en ejecución y los recursos del sistema.

Al finalizar podrá

  • descargar una imagen desde Docker Hub;
  • crear y ejecutar un contenedor en segundo plano;
  • publicar un puerto para acceder a una aplicación desde el sistema anfitrión;
  • comprobar el estado de un contenedor y acceder a la aplicación que ejecuta;
  • consultar registros, configuración y consumo de recursos;
  • detener, iniciar, reiniciar y eliminar contenedores;
  • ejecutar varias instancias de una misma imagen mediante puertos diferentes;
  • ejecutar comandos dentro de un contenedor en funcionamiento.

Compruebe que dispone de los siguientes elementos.

Requisito Comprobación
Docker instalado docker --version
Docker daemon en ejecución docker info
Conexión a internet Necesaria para descargar la imagen
Puerto 8080 disponible lsof -i :8080 no debería mostrar procesos escuchando en ese puerto
Navegador web Necesario para acceder a la aplicación

Verifique primero que el comando de Docker esté disponible.

Ventana de terminal
docker --version

Importante

Si el comando docker no es reconocido o devuelve un error de permisos, resuelva primero la instalación o configuración de Docker antes de continuar.

Antes de descargar la aplicación, observe el estado inicial de Docker. Estas comprobaciones le permitirán comparar el sistema antes y después de crear el contenedor.

Ejecute

Ventana de terminal
docker info

La salida incluye información sobre el daemon de Docker y los recursos que administra, entre ellos contenedores e imágenes.

Ventana de terminal
docker images

Si es una instalación reciente, la lista puede estar vacía o contener únicamente imágenes utilizadas en pruebas anteriores.

Ventana de terminal
docker ps

Revise especialmente la columna PORTS para comprobar que ningún contenedor esté utilizando el puerto 8080.

Nota

docker ps permite identificar contenedores administrados por Docker. Si necesita comprobar si otro proceso del sistema utiliza el puerto 8080, puede ejecutar lsof -i :8080.

Una imagen proporciona el sistema de archivos y la configuración base que Docker utilizará para crear un contenedor.

Descargue la imagen de Grocery List App desde Docker Hub.

Ventana de terminal
docker pull jpadillaa/grocerylistapp:latest

Durante la descarga puede aparecer una salida similar a esta.

latest: Pulling from jpadillaa/grocerylistapp
a2abf6c4d29d: Pull complete
c5608244554d: Pull complete
2a13d2c24a3c: Pull complete
3f4efb95c5e5: Pull complete
Digest: sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Status: Downloaded newer image for jpadillaa/grocerylistapp:latest
docker.io/jpadillaa/grocerylistapp:latest

Cada mensaje Pull complete corresponde a una capa de la imagen que Docker necesitó descargar. El uso de capas permite reutilizar contenido compartido entre imágenes y evitar descargas innecesarias cuando una capa ya está disponible localmente.

Ventana de terminal
docker images

La imagen debería aparecer entre los recursos locales.

REPOSITORY TAG IMAGE ID CREATED SIZE
jpadillaa/grocerylistapp latest xxxxxxxxxxxx X days ago XXX MB

Hasta este punto solo existe la imagen. Todavía no se ha creado ningún contenedor a partir de ella.

Utilice la imagen descargada para crear una instancia de la aplicación.

Ventana de terminal
docker run -d -p 8080:8080 --name app jpadillaa/grocerylistapp:latest

Docker devolverá un identificador similar al siguiente.

a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2

Ese valor corresponde al identificador completo del contenedor creado.

Elemento Función
docker run Crea un contenedor y ejecuta su proceso principal
-d Ejecuta el contenedor en segundo plano
-p 8080:8080 Publica el puerto 8080 del contenedor mediante el puerto 8080 del sistema anfitrión
--name app Asigna el nombre app al contenedor
jpadillaa/grocerylistapp:latest Indica la imagen y el tag utilizados para crear el contenedor

La publicación del puerto establece este recorrido.

Navegador
│
│ http://localhost:8080
▼
Sistema anfitrión
│
│ puerto 8080
▼
Contenedor "app"
│
│ puerto 8080
▼
Grocery List App

La aplicación escucha en el puerto 8080 dentro del contenedor. La opción -p permite acceder a ese servicio mediante el puerto 8080 del sistema anfitrión.

Comprobar que el contenedor está en ejecución

Sección titulada «Comprobar que el contenedor está en ejecución»
Ventana de terminal
docker ps

Una salida aproximada puede verse así.

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a1b2c3d4e5f6 jpadillaa/grocerylistapp:latest "java -jar /app/app...." 10 seconds ago Up 9 seconds 0.0.0.0:8080->8080/tcp app

Las columnas permiten reconocer información distinta sobre el contenedor.

Columna Significado
CONTAINER ID Identificador abreviado
IMAGE Imagen utilizada para crear el contenedor
COMMAND Proceso iniciado al ejecutar el contenedor
CREATED Tiempo transcurrido desde su creación
STATUS Estado actual
PORTS Puertos publicados
NAMES Nombre asignado

El contenedor app debería aparecer con estado Up y una publicación que relacione el puerto 8080 del sistema anfitrión con el puerto 8080 del contenedor.

Abra en el navegador

http://localhost:8080

Debería aparecer la interfaz de Grocery List App.

Realice algunas operaciones para comprobar que la aplicación responde.

  1. Agregue un elemento a la lista, por ejemplo Manzanas.
  2. Agregue un segundo elemento, por ejemplo Leche.
  3. Marque uno de los elementos como completado.
  4. Elimine un elemento.

Estas acciones comprueban algo diferente a docker ps. El comando confirma que el contenedor está en ejecución, mientras que la interacción con la aplicación permite comprobar que el servicio responde a solicitudes.

Si no dispone de un navegador gráfico, puede solicitar directamente el contenido.

Ventana de terminal
curl http://localhost:8080

También puede consultar únicamente los encabezados de la respuesta HTTP.

Ventana de terminal
curl -I http://localhost:8080

El laboratorio original muestra una respuesta similar a esta.

HTTP/1.1 200 OK
Server: gunicorn
Date: Mon, 22 Dec 2025 23:51:16 GMT
Connection: close
Content-Type: text/html; charset=utf-8
Content-Length: 2291

Un código HTTP 200 indica que el servidor respondió correctamente a la solicitud.

Sugerencia

Si la aplicación no carga, consulte primero los registros con docker logs app.

Observar el contenedor durante la ejecución

Sección titulada «Observar el contenedor durante la ejecución»

Una vez que el servicio funciona, Docker permite observar diferentes aspectos de su ejecución sin detenerlo.

Ventana de terminal
docker logs app

El comando muestra la salida estándar y la salida de error producidas por el proceso principal del contenedor.

Para seguir los nuevos registros a medida que se generan, utilice

Ventana de terminal
docker logs -f app

Presione Ctrl + C cuando desee dejar de seguir la salida.

Ventana de terminal
docker inspect app

docker inspect devuelve una representación detallada de la configuración y el estado del contenedor. Cuando solo necesita un dato concreto, puede utilizar una plantilla de formato.

Consulte la dirección IP asignada al contenedor.

Ventana de terminal
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' app

Consulte las variables de entorno.

Ventana de terminal
docker inspect -f '{{range .Config.Env}}{{println .}}{{end}}' app

Consulte el estado actual.

Ventana de terminal
docker inspect -f '{{.State.Status}}' app
Ventana de terminal
docker stats app --no-stream

Una salida aproximada puede verse así.

CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
a1b2c3d4e5f6 app 0.15% 150MiB / 7.5GiB 2.00% 1.5kB / 1.2kB 0B / 0B 25

Este comando permite observar métricas como CPU, memoria, tráfico de red, operaciones de entrada y salida y número de procesos.

Crear un contenedor no implica que deba permanecer en ejecución de forma permanente. Docker separa la existencia del contenedor de su estado de ejecución.

Ventana de terminal
docker stop app

Compruebe que ya no aparece entre los contenedores activos.

Ventana de terminal
docker ps

docker stop detiene el proceso principal, pero no elimina el contenedor.

Consultar también los contenedores detenidos

Sección titulada «Consultar también los contenedores detenidos»
Ventana de terminal
docker ps -a

Puede aparecer una salida similar a esta.

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a1b2c3d4e5f6 jpadillaa/grocerylistapp:latest "java -jar /app/app...." 5 minutes ago Exited (143) 1 minute ago app

El cambio de Up a Exited indica que el contenedor sigue existiendo, aunque su proceso principal ya no esté en ejecución.

El laboratorio original utiliza el código 143 como ejemplo de una terminación asociada con SIGTERM.

Ventana de terminal
docker start app

Compruebe su estado.

Ventana de terminal
docker ps

La aplicación debería volver a estar disponible en

http://localhost:8080

docker start no crea un nuevo contenedor. Reinicia el que ya existía.

Ventana de terminal
docker restart app

Este comando detiene y vuelve a iniciar el mismo contenedor.

Cuando ya no necesite la instancia creada durante el laboratorio, deténgala y elimínela.

Ventana de terminal
docker stop app
docker rm app

Compruebe que desapareció de la lista.

Ventana de terminal
docker ps -a

La imagen sigue almacenada localmente aunque el contenedor haya sido eliminado. Puede comprobarlo con

Ventana de terminal
docker images

Si tampoco necesita conservar la imagen, elimínela.

Ventana de terminal
docker rmi jpadillaa/grocerylistapp:latest

Nota

Eliminar la imagen implica que Docker deberá descargarla nuevamente si desea crear otro contenedor a partir de ella.

La imagen y el contenedor son recursos distintos. Una imagen puede utilizarse para crear varios contenedores y puede permanecer disponible después de eliminar cualquiera de ellos.

Del mismo modo, detener un contenedor no equivale a eliminarlo. Mientras exista, puede volver a iniciarse con docker start.

Los siguientes ejercicios modifican una propiedad de la ejecución para observar cómo cambia el comportamiento del contenedor.

Ejercicio 1 - Utilizar otro puerto del sistema anfitrión

Sección titulada «Ejercicio 1 - Utilizar otro puerto del sistema anfitrión»

Ejecute la aplicación mediante el puerto 3000, manteniendo el puerto 8080 dentro del contenedor.

Ventana de terminal
docker run -d -p 3000:8080 --name app-puerto3000 jpadillaa/grocerylistapp:latest

Acceda a

http://localhost:3000

Observe que no fue necesario modificar el puerto utilizado por la aplicación dentro del contenedor. Solo cambió el puerto publicado en el sistema anfitrión.

Ejecute el contenedor sin -d.

Ventana de terminal
docker run --rm -p 8080:8080 --name app-foreground jpadillaa/grocerylistapp:latest

Los registros del proceso aparecerán directamente en la terminal.

Presione Ctrl + C para detenerlo. La opción --rm hace que Docker elimine automáticamente el contenedor cuando termina.

Ejercicio 3 - Ejecutar múltiples instancias

Sección titulada «Ejercicio 3 - Ejecutar múltiples instancias»

Cree dos contenedores a partir de la misma imagen y publique cada instancia mediante un puerto diferente.

Ventana de terminal
# Primera instancia
docker run -d -p 8081:8080 --name app-1 jpadillaa/grocerylistapp:latest
# Segunda instancia
docker run -d -p 8082:8080 --name app-2 jpadillaa/grocerylistapp:latest
# Comprobar ambas instancias
docker ps

Acceda a la primera instancia en

http://localhost:8081

y a la segunda en

http://localhost:8082

Las dos instancias utilizan la misma imagen, pero son contenedores independientes con nombres e interfaces de acceso diferentes.

Ejercicio 4 - Eliminar automáticamente el contenedor

Sección titulada «Ejercicio 4 - Eliminar automáticamente el contenedor»

Ejecute una instancia temporal.

Ventana de terminal
docker run --rm -d -p 8080:8080 --name app-temporal jpadillaa/grocerylistapp:latest

Deténgala y compruebe si continúa registrada.

Ventana de terminal
docker stop app-temporal
docker ps -a | grep app-temporal

El contenedor no debería aparecer porque --rm solicita su eliminación cuando termina.

Ejercicio 5 - Ejecutar comandos dentro del contenedor

Sección titulada «Ejercicio 5 - Ejecutar comandos dentro del contenedor»

Cree una instancia si todavía no tiene app en ejecución.

Ventana de terminal
docker run -d -p 8080:8080 --name app jpadillaa/grocerylistapp:latest

Abra un shell dentro del contenedor.

Ventana de terminal
docker exec -it app /bin/sh

Una vez dentro, explore algunos archivos.

Ventana de terminal
ls -la /app
cat /etc/os-release
exit

docker exec no crea otro contenedor. Inicia un proceso adicional dentro de uno que ya está en ejecución.

Advertencia

El laboratorio original propone el siguiente comando para detener y eliminar los contenedores después de los ejercicios.

Ventana de terminal
docker stop $(docker ps -q) && docker rm $(docker ps -aq)

Este comando actúa sobre todos los contenedores Docker del sistema, no únicamente sobre los creados en este laboratorio. No lo utilice si necesita conservar otros contenedores en ejecución o detenidos.

¿Qué sucede si utiliza un nombre que ya pertenece a otro contenedor?

Sección titulada «¿Qué sucede si utiliza un nombre que ya pertenece a otro contenedor?»

Docker no permite que dos contenedores existentes tengan el mismo nombre. Si app ya existe, un nuevo docker run --name app ... producirá un conflicto similar al siguiente.

docker: Error response from daemon: Conflict. The container name "/app" is already in use by container "abc123...".

Puede eliminar el contenedor existente con docker rm app cuando corresponda o asignar un nombre diferente al nuevo contenedor.

¿Cuál es la diferencia entre docker stop y docker kill?

Sección titulada «¿Cuál es la diferencia entre docker stop y docker kill?»

Según la explicación del laboratorio original, docker stop solicita una terminación ordenada mediante SIGTERM y, si el proceso no finaliza dentro del tiempo de espera, Docker fuerza su terminación. docker kill fuerza la terminación de forma inmediata.

La diferencia relevante es que docker stop ofrece al proceso la oportunidad de finalizar de manera controlada antes de recurrir a una terminación forzada.

La aplicación escucha en el puerto 8080 dentro del contenedor. La opción -p 8080:8080 publica ese puerto mediante el puerto 8080 del sistema anfitrión y permite acceder a la aplicación desde localhost.

Sin esa publicación, ejecutar el contenedor no hace que el servicio sea accesible automáticamente mediante ese puerto del host.

¿Qué ocurre con los datos almacenados dentro del contenedor cuando se elimina?

Sección titulada «¿Qué ocurre con los datos almacenados dentro del contenedor cuando se elimina?»

Los cambios almacenados únicamente en la capa escribible del contenedor desaparecen al eliminarlo. Cuando una aplicación necesita conservar información más allá del ciclo de vida de un contenedor, debe utilizar un mecanismo de persistencia independiente, como los volúmenes estudiados en el Laboratorio 03.

Un nombre permite referirse al contenedor de forma estable y legible.

En lugar de recordar un identificador puede utilizar comandos como

Ventana de terminal
docker logs app
docker stop app
docker inspect app

Esto también facilita el uso del contenedor desde scripts y procedimientos reproducibles.

Después de completar el laboratorio debería poder distinguir con claridad entre una imagen, un contenedor y el estado de ejecución de ese contenedor.

La imagen jpadillaa/grocerylistapp:latest proporciona la base para crear instancias. Cada ejecución de docker run crea un contenedor independiente. Ese contenedor puede estar en ejecución o detenido, puede observarse mediante logs, inspect y stats, y finalmente puede eliminarse sin que eso implique necesariamente eliminar la imagen.

También debería poder interpretar los principales elementos utilizados durante el ejercicio.

Comando Propósito
docker pull <imagen> Descarga una imagen desde un registro
docker images Lista las imágenes almacenadas localmente
docker run ... Crea y ejecuta un contenedor
docker ps Lista los contenedores en ejecución
docker ps -a Lista contenedores en cualquier estado
docker logs <nombre> Consulta los registros del proceso principal
docker logs -f <nombre> Sigue nuevos registros en tiempo real
docker stop <nombre> Detiene un contenedor
docker start <nombre> Inicia un contenedor detenido
docker restart <nombre> Reinicia un contenedor
docker rm <nombre> Elimina un contenedor
docker rmi <imagen> Elimina una imagen
docker inspect <nombre> Consulta configuración y estado detallados
docker stats <nombre> Consulta métricas de consumo de recursos
docker exec -it <nombre> <comando> Ejecuta un proceso adicional dentro de un contenedor
Recurso Enlace
Docker Run Reference Documentación de docker run
Docker Hub Docker Hub

Fuente original

Laboratorio 04 - Ejecución de contenedores Docker