Ir al contenido

Laboratorio 03 - Gestión de contenedores y servicios con Docker

En los laboratorios anteriores ejecutó contenedores a partir de imágenes existentes. En este laboratorio avanzará hacia un flujo de trabajo más completo. Desplegará un servidor web Apache con contenido personalizado, ejecutará PostgreSQL con persistencia de datos y utilizará herramientas de Docker para inspeccionar, diagnosticar y limpiar los recursos creados.

El propósito es observar el ciclo de vida de un contenedor y relacionarlo con tres conceptos que aparecen de forma recurrente en Docker. La publicación de puertos permite acceder a servicios desde el sistema anfitrión, los montajes permiten separar datos y contenido del ciclo de vida del contenedor, y las herramientas de diagnóstico permiten comprender qué ocurre durante la ejecución.

Al finalizar podrá

  • desplegar un servidor web Apache a partir de una versión específica de una imagen;
  • publicar puertos para acceder desde el sistema anfitrión a servicios que se ejecutan dentro de un contenedor;
  • utilizar un bind mount para servir contenido almacenado en el sistema anfitrión;
  • crear un volumen nombrado y utilizarlo para conservar datos de PostgreSQL;
  • configurar un contenedor mediante variables de entorno;
  • inspeccionar contenedores y revisar sus registros de ejecución;
  • ejecutar comandos dentro de un contenedor en funcionamiento;
  • eliminar contenedores, volúmenes e imágenes cuando ya no sean necesarios.
Fase Servicio Conceptos principales
1 Servidor web Apache Imágenes y tags, publicación de puertos, contenido personalizado y bind mounts
2 Base de datos PostgreSQL Variables de entorno, volúmenes nombrados y persistencia
3 Diagnóstico y limpieza inspect, logs, exec y gestión de recursos

Necesitará

  • Docker instalado y en ejecución;
  • una terminal con acceso a Docker;
  • los puertos 8080 y 5432 disponibles en su equipo;
  • un editor de texto.

Si configuró previamente el grupo docker, no debería necesitar sudo para ejecutar los comandos de Docker.

Compruebe que Docker está disponible y que puede consultar los contenedores del sistema.

Ventana de terminal
docker --version
docker ps

Una imagen puede publicarse con diferentes tags. Cada tag identifica una variante o versión que puede tener diferencias en software, dependencias o sistema base.

Descargue primero la versión estándar de Apache HTTP Server.

Ventana de terminal
docker pull httpd:2.4

Descargue después la variante basada en Alpine Linux.

Ventana de terminal
docker pull httpd:2.4-alpine

Consulte las imágenes disponibles.

Ventana de terminal
docker images httpd

Una salida aproximada puede verse así.

REPOSITORY TAG IMAGE ID CREATED SIZE
httpd 2.4 f84fe51ff5d3 10 days ago 250MB
httpd 2.4-alpine c7b8040505e2 3 years ago 82.8MB

Nota

La variante Alpine ocupa menos espacio porque utiliza Alpine Linux como sistema base. En este laboratorio se utilizará httpd:2.4.

Apache escucha en el puerto 80 dentro del contenedor. Para acceder al servicio desde el sistema anfitrión, publique ese puerto mediante el puerto 8080.

Ventana de terminal
docker run -d --name mi-apache -p 8080:80 httpd:2.4

Las opciones utilizadas cumplen funciones diferentes.

Elemento Función
-d Ejecuta el contenedor en segundo plano
--name mi-apache Asigna el nombre mi-apache al contenedor
-p 8080:80 Publica el puerto 80 del contenedor mediante el puerto 8080 del sistema anfitrión
httpd:2.4 Indica la imagen y el tag utilizados para crear el contenedor

Compruebe que el contenedor continúa en ejecución.

Ventana de terminal
docker ps

Abra después la siguiente dirección en el navegador.

http://localhost:8080

Debería aparecer el mensaje It works!.

El proceso de Apache se ejecuta dentro del contenedor y escucha en su puerto 80. La opción -p 8080:80 crea la publicación necesaria para que una conexión dirigida al puerto 8080 del sistema anfitrión llegue al servicio que escucha dentro del contenedor.

Hasta este punto Apache utiliza el contenido incluido en la imagen. El siguiente paso reemplaza ese contenido por archivos almacenados en el sistema anfitrión.

Detenga y elimine el contenedor actual.

Ventana de terminal
docker stop mi-apache
docker rm mi-apache

Cree un directorio para el sitio web.

Ventana de terminal
mkdir -p ~/docker-laboratorio/sitio-web

Cree el archivo index.html.

Ventana de terminal
cat > ~/docker-laboratorio/sitio-web/index.html << 'EOF'
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Mi Servidor Docker</title>
<style>
body { font-family: Arial, sans-serif; max-width: 600px; margin: 50px auto; text-align: center; }
.container { background: #f0f8ff; border-radius: 10px; padding: 30px; }
h1 { color: #2496ED; }
.info { background: #e8f5e9; padding: 15px; border-radius: 5px; margin-top: 20px; text-align: left; }
</style>
</head>
<body>
<div class="container">
<h1>Servidor Apache en Docker</h1>
<p>Esta página se sirve desde un contenedor Docker con contenido montado desde el host.</p>
<div class="info">
<strong>Detalles técnicos</strong>
<ul>
<li>Imagen — httpd:2.4</li>
<li>Puerto del contenedor — 80</li>
<li>Puerto del host — 8080</li>
<li>Volumen — bind mount</li>
</ul>
</div>
</div>
</body>
</html>
EOF

Ejecute Apache nuevamente y monte el directorio local sobre el directorio que Apache utiliza para servir archivos.

Ventana de terminal
docker run -d \
--name mi-apache \
-p 8080:80 \
-v ~/docker-laboratorio/sitio-web:/usr/local/apache2/htdocs/:ro \
httpd:2.4

La expresión utilizada con -v relaciona dos rutas. La primera pertenece al sistema anfitrión y la segunda pertenece al contenedor.

~/docker-laboratorio/sitio-web
↓
/usr/local/apache2/htdocs/

El sufijo :ro monta el directorio en modo de solo lectura. El contenedor puede leer los archivos, pero no modificarlos mediante ese montaje.

Abra nuevamente

http://localhost:8080

Ahora debería aparecer la página almacenada en su directorio local.

Modificar el contenido sin recrear el contenedor

Sección titulada «Modificar el contenido sin recrear el contenedor»

Agregue una nueva línea al archivo del sistema anfitrión.

Ventana de terminal
echo '<p style="color: green; font-weight: bold;">¡Contenido actualizado sin reiniciar el contenedor!</p>' >> ~/docker-laboratorio/sitio-web/index.html

Recargue la página en el navegador.

El cambio aparece porque Apache lee el contenido desde el directorio montado. No fue necesario detener ni recrear el contenedor.

Nota

Mantenga mi-apache en ejecución. Se utilizará más adelante durante la sección de diagnóstico.

El ciclo de vida del contenido dejó de depender del sistema de archivos interno del contenedor. Los archivos permanecen en el sistema anfitrión y el contenedor los utiliza mediante el montaje.

Este patrón también permite modificar los archivos desde el host y observar los cambios inmediatamente desde la aplicación que se ejecuta en el contenedor.

Una base de datos requiere conservar información incluso cuando el contenedor que ejecuta el servidor se elimina. Para separar esos dos ciclos de vida utilizará un volumen nombrado.

Cree el volumen.

Ventana de terminal
docker volume create pgdata-laboratorio

Compruebe que existe e inspeccione su configuración.

Ventana de terminal
docker volume ls
docker volume inspect pgdata-laboratorio

En un volumen nombrado, Docker administra la ubicación donde se almacenan los datos. El contenedor utiliza el volumen mediante un nombre en lugar de depender de una ruta elegida directamente en el sistema anfitrión.

PostgreSQL utiliza variables de entorno durante la inicialización. En lugar de escribir las credenciales directamente en docker run, cree un archivo .env.

Ventana de terminal
cat > ~/docker-laboratorio/.env << 'EOF'
POSTGRES_USER=estudiante
POSTGRES_PASSWORD=docker2025
POSTGRES_DB=universidad
EOF

Advertencia

En un proyecto real, un archivo .env con credenciales no debe incluirse en el repositorio de código. Inclúyalo en .gitignore cuando corresponda.

Inicie el contenedor y asocie el volumen pgdata-laboratorio con el directorio utilizado por PostgreSQL para almacenar sus datos.

Ventana de terminal
docker run -d \
--name mi-postgres \
-p 5432:5432 \
--env-file ~/docker-laboratorio/.env \
-v pgdata-laboratorio:/var/lib/postgresql/data \
postgres:17.5

Compruebe que el contenedor está en ejecución.

Ventana de terminal
docker ps

La inicialización de PostgreSQL puede tardar algunos segundos. Consulte los registros del contenedor.

Ventana de terminal
docker logs mi-postgres

Continúe cuando aparezca el siguiente mensaje.

database system is ready to accept connections

El contenedor combina tres mecanismos estudiados hasta este momento.

Mecanismo Configuración utilizada
Publicación de puertos -p 5432:5432
Variables de entorno --env-file ~/docker-laboratorio/.env
Persistencia -v pgdata-laboratorio:/var/lib/postgresql/data

El proceso de PostgreSQL pertenece al contenedor. Los datos almacenados en /var/lib/postgresql/data, en cambio, se escriben en el volumen nombrado.

Abra una sesión de psql dentro del contenedor.

Ventana de terminal
docker exec -it mi-postgres psql -U estudiante -d universidad

Cree una tabla e inserte algunos registros.

CREATE TABLE cursos (
id SERIAL PRIMARY KEY,
nombre VARCHAR(100) NOT NULL,
creditos INTEGER NOT NULL,
semestre VARCHAR(10)
);
INSERT INTO cursos (nombre, creditos, semestre) VALUES
('Desarrollo Cloud', 4, '2025-2'),
('Ingeniería de Software', 3, '2025-2'),
('Bases de Datos Avanzadas', 3, '2025-1'),
('Inteligencia Artificial', 4, '2025-2');
SELECT * FROM cursos;

Una salida esperada es similar a esta.

id | nombre | creditos | semestre
----+--------------------------+----------+----------
1 | Desarrollo Cloud | 4 | 2025-2
2 | Ingeniería de Software | 3 | 2025-2
3 | Bases de Datos Avanzadas | 3 | 2025-1
4 | Inteligencia Artificial | 4 | 2025-2
(4 rows)

Salga de psql.

\q

Detenga y elimine mi-postgres.

Ventana de terminal
docker stop mi-postgres
docker rm mi-postgres

Compruebe que el contenedor ya no existe.

Ventana de terminal
docker ps -a | grep mi-postgres

Cree un nuevo contenedor y vuelva a conectar el mismo volumen.

Ventana de terminal
docker run -d \
--name mi-postgres \
-p 5432:5432 \
--env-file ~/docker-laboratorio/.env \
-v pgdata-laboratorio:/var/lib/postgresql/data \
postgres:17.5

Espere a que PostgreSQL complete la inicialización y consulte nuevamente la tabla.

Ventana de terminal
docker exec -it mi-postgres psql -U estudiante -d universidad -c "SELECT * FROM cursos;"

Los registros creados anteriormente deberían seguir disponibles.

El contenedor utilizado inicialmente fue eliminado. Los datos sobrevivieron porque no dependían de su sistema de archivos efímero, sino del volumen pgdata-laboratorio.

La prueba separa dos ciclos de vida. El contenedor puede destruirse y recrearse, mientras que el volumen puede mantenerse y conectarse a una nueva instancia del servicio.

Hasta este momento utilizó Docker para crear y ejecutar servicios. Las siguientes herramientas permiten observar el estado de esos servicios durante la ejecución.

docker inspect devuelve información detallada sobre la configuración y el estado de un objeto administrado por Docker.

Una consulta general puede producir una salida extensa.

Ventana de terminal
docker inspect mi-postgres

Si solo desea localizar la dirección IP en esa salida, puede utilizar

Ventana de terminal
docker inspect mi-postgres | grep -i ipaddress

Para obtener valores concretos, --format permite seleccionar campos específicos.

Ventana de terminal
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' mi-postgres

Consulte los puertos publicados.

Ventana de terminal
docker inspect --format='{{json .NetworkSettings.Ports}}' mi-postgres

Consulte las variables de entorno disponibles en el contenedor.

Ventana de terminal
docker inspect --format='{{json .Config.Env}}' mi-postgres

Sugerencia

Si tiene jq instalado, puede utilizarlo para explorar con mayor comodidad las estructuras JSON que devuelve docker inspect.

Ventana de terminal
docker inspect mi-postgres | jq '.[0].NetworkSettings.Networks'

Los registros permiten observar la salida generada por el proceso principal del contenedor.

Consulte las últimas 20 líneas de Apache.

Ventana de terminal
docker logs --tail 20 mi-apache

Siga los nuevos registros en tiempo real.

Ventana de terminal
docker logs -f mi-apache

Mientras el comando permanece activo, abra http://localhost:8080 varias veces desde otra terminal o desde el navegador. Las solicitudes HTTP deberían aparecer en los registros.

Presione Ctrl + C para dejar de seguir la salida.

Para PostgreSQL puede solicitar además marcas de tiempo.

Ventana de terminal
docker logs -t --tail 10 mi-postgres

docker exec inicia un proceso adicional dentro de un contenedor que ya está en ejecución. Esto permite consultar archivos, ejecutar herramientas de diagnóstico o abrir una sesión interactiva sin detener el servicio principal.

Consulte la versión del servidor.

Ventana de terminal
docker exec mi-apache httpd -v

Liste los archivos que Apache está sirviendo.

Ventana de terminal
docker exec mi-apache ls -la /usr/local/apache2/htdocs/

Consulte información sobre el sistema operativo base.

Ventana de terminal
docker exec mi-apache cat /etc/os-release

Compruebe si PostgreSQL está listo para recibir conexiones.

Ventana de terminal
docker exec mi-postgres pg_isready -U estudiante

Ejecute una consulta sin abrir una sesión interactiva.

Ventana de terminal
docker exec mi-postgres psql -U estudiante -d universidad -c "SELECT nombre, creditos FROM cursos WHERE creditos >= 4;"

Abra una sesión de Bash dentro del contenedor.

Ventana de terminal
docker exec -it mi-postgres bash

Dentro de esa sesión puede explorar el sistema de archivos o consultar procesos. Para salir, ejecute

Ventana de terminal
exit

Docker puede mostrar cuánto espacio ocupan sus principales tipos de recursos.

Ventana de terminal
docker system df

Una salida aproximada puede verse así.

TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 3 2 332.8MB 82.8MB (24%)
Containers 2 2 63B 0B (0%)
Local Volumes 1 1 40MB 0B (0%)
Build Cache 0 0 0B 0B

La columna RECLAIMABLE indica espacio asociado con recursos que Docker considera recuperables.

La limpieza forma parte del ciclo de vida de los recursos creados durante las pruebas. En esta sección eliminará primero los contenedores y después los recursos que ya no necesitan conservarse.

Ventana de terminal
docker stop mi-apache mi-postgres
docker rm mi-apache mi-postgres

Compruebe el estado final.

Ventana de terminal
docker ps -a
Ventana de terminal
docker volume rm pgdata-laboratorio

Compruebe que el volumen ya no aparece.

Ventana de terminal
docker volume ls

Advertencia

Eliminar un volumen borra los datos almacenados en él. En un entorno real, asegúrese de contar con el respaldo necesario antes de eliminar un volumen que contenga información que deba conservarse.

Ventana de terminal
docker rmi httpd:2.4 httpd:2.4-alpine postgres:17.5

Revise primero el uso de espacio.

Ventana de terminal
docker system df

Docker puede eliminar recursos que ya no están siendo utilizados.

Ventana de terminal
docker system prune

Para incluir volúmenes huérfanos puede utilizar

Ventana de terminal
docker system prune --volumes

Advertencia

docker system prune --volumes no se limita a los recursos de este laboratorio. Puede eliminar volúmenes huérfanos asociados con otros proyectos del mismo sistema. Revise el entorno antes de ejecutarlo.

Ventana de terminal
rm -rf ~/docker-laboratorio

Identifique el proceso que utiliza el puerto.

Ventana de terminal
sudo lsof -i :8080

También puede publicar Apache mediante otro puerto del sistema anfitrión.

Ventana de terminal
docker run -d --name mi-apache -p 9090:80 httpd:2.4

En ese caso, el servicio quedará disponible en

http://localhost:9090

Compruebe si existe otro proceso escuchando en ese puerto.

Ventana de terminal
sudo lsof -i :5432

Si se trata de una instalación local de PostgreSQL y desea detenerla, puede utilizar

Ventana de terminal
sudo systemctl stop postgresql

Otra alternativa consiste en publicar el puerto 5432 del contenedor mediante otro puerto del sistema anfitrión.

Ventana de terminal
docker run -d --name mi-postgres -p 5433:5432 ...

Consulte primero sus registros.

Ventana de terminal
docker logs mi-postgres

Compruebe después el estado del contenedor y su código de salida.

Ventana de terminal
docker ps -a --filter "name=mi-postgres"

Aparece un error de permisos al utilizar el bind mount

Sección titulada «Aparece un error de permisos al utilizar el bind mount»

Compruebe los permisos del directorio local.

Ventana de terminal
ls -la ~/docker-laboratorio/sitio-web/

El laboratorio original propone como alternativa crear un volumen nombrado.

Ventana de terminal
docker volume create apache-content

Este comando crea el volumen, pero no sustituye por sí solo el montaje utilizado por Apache. Para utilizarlo sería necesario ejecutar el contenedor con una configuración que monte ese volumen en el directorio correspondiente.

Después de completar el laboratorio debería poder distinguir varias responsabilidades dentro de una ejecución de Docker.

  • Una imagen proporciona la base utilizada para crear un contenedor.
  • Un tag identifica una variante concreta de una imagen.
  • Un contenedor ejecuta uno o más procesos a partir de esa imagen.
  • La opción -p publica un puerto del contenedor mediante un puerto del sistema anfitrión.
  • Un bind mount conecta una ruta del sistema anfitrión con una ruta del contenedor.
  • Un volumen nombrado permite conservar datos fuera del ciclo de vida de un contenedor específico.
  • Un archivo utilizado con --env-file proporciona variables de entorno durante la creación del contenedor.
  • docker inspect permite consultar configuración y estado.
  • docker logs permite revisar la salida generada por el proceso del contenedor.
  • docker exec permite iniciar procesos adicionales dentro de un contenedor en ejecución.

Los ejemplos de Apache y PostgreSQL muestran que crear un contenedor es solo una parte del trabajo. Una ejecución útil también requiere decidir cómo exponer el servicio, dónde conservar los datos, cómo proporcionar configuración, cómo observar su comportamiento y qué recursos deben permanecer después de eliminar el contenedor.

Recurso Enlace
Docker CLI Referencia de Docker CLI
Volúmenes de Docker Documentación de volúmenes
Redes de Docker Documentación de networking
Imagen httpd Docker Hub
Imagen postgres Docker Hub

Fuente original

Laboratorio 03 - Gestión de contenedores y servicios con Docker