En esta lección culminamos el primer módulo poniendo en práctica todo lo aprendido: vamos a crear y ejecutar contenedores paso a paso. Veremos cómo lanzar un contenedor en modo interactivo (-it) para "entrar" en él, cómo ejecutarlo en segundo plano (-d) para que funcione como un servicio, cómo mapear puertos para acceder a la aplicación desde tu navegador y cómo darle un nombre legible. Terminaremos con un ejemplo completo y muy satisfactorio: levantar un servidor web Nginx y verlo funcionando en tu navegador. Este es el momento en que Docker deja de ser teoría y se vuelve una herramienta tangible.
Objetivos de Aprendizaje
- Ejecutar un contenedor desde cero, paso a paso.
- Usar el modo interactivo
-itpara entrar en un contenedor. - Usar el modo detached
-dpara ejecutar contenedores en segundo plano. - Mapear puertos del host al contenedor con
-p. - Asignar nombres legibles a los contenedores con
--name. - Levantar un servidor Nginx accesible desde el navegador.
El Modo Interactivo: -it
A veces queremos "entrar" en un contenedor para explorarlo o probar comandos dentro de él, como si fuera una pequeña máquina Linux. Para eso se usa el modo interactivo.
docker run: crea y arranca un contenedor.-it: combinación de dos opciones.-i(--interactive) mantiene abierta la entrada estándar, y-t(--tty) asigna una terminal. Juntas te ofrecen una shell utilizable.ubuntu: la imagen a usar (una versión mínima de Ubuntu).bash: el comando a ejecutar al arrancar; en este caso, una shell Bash.
Al ejecutarlo, tu prompt cambiará: ahora estás dentro del contenedor. Puedes probar comandos de Linux:
cat /etc/os-release: muestra qué sistema operativo corre dentro del contenedor (verás que es Ubuntu, aunque tu host sea Windows o macOS).ls /: lista el sistema de ficheros raíz del contenedor.whoami: muestra el usuario actual (normalmenteroot).
Para salir del contenedor y volver a tu terminal habitual:
exit: cierra la shell. Como era el proceso principal del contenedor, este se detiene al salir.
El Modo Detached: -d
Para servicios que deben seguir funcionando (un servidor web, una base de datos…), no queremos quedarnos "dentro": queremos que se ejecuten en segundo plano y devolvernos el control de la terminal. Eso es el modo detached.
-d(--detach): ejecuta el contenedor en segundo plano.- En lugar de mostrarte la salida del contenedor, Docker imprime el ID del contenedor y te devuelve el control de la terminal de inmediato.
El contenedor sigue ejecutándose; puedes comprobarlo con docker ps. Para ver su salida en cualquier momento, recuerda que dispones de docker logs.
| Modo | Opción | Cuándo usarlo | Comportamiento |
|---|---|---|---|
| Interactivo | -it |
Explorar, depurar, ejecutar comandos manuales | Te "mete" dentro del contenedor |
| Detached | -d |
Servicios de larga duración (web, BBDD…) | Corre en segundo plano, libera terminal |
Mapeo de Puertos: -p
Un contenedor está aislado por defecto: aunque dentro de él haya un servidor web escuchando en el puerto 80, desde fuera no puedes acceder a menos que publiques ese puerto. El mapeo de puertos crea un "puente" entre un puerto de tu máquina (el host) y un puerto del contenedor.
-p 8080:80: publica el puerto. La sintaxis esPUERTO_HOST:PUERTO_CONTENEDOR.8080: el puerto en tu máquina (el host).80: el puerto dentro del contenedor donde escucha Nginx.
- Resultado: cuando visitas
http://localhost:8080, el tráfico se redirige al puerto 80 del contenedor.
Es muy fácil confundir el orden, así que recuérdalo: primero el host, luego el contenedor (host:contenedor).
Nombrar Contenedores: --name
Si no le das un nombre, Docker asigna a cada contenedor un nombre aleatorio simpático (como nostalgic_einstein). Para gestionarlos cómodamente, conviene ponerles nombres descriptivos.
--name mi_servidor_web: asigna un nombre legible al contenedor.- A partir de ahora puedes referirte a él por su nombre en cualquier comando:
docker logs mi_servidor_web,docker stop mi_servidor_web, etc.
Ten en cuenta que los nombres deben ser únicos: no puede haber dos contenedores con el mismo nombre a la vez (aunque uno esté detenido). Si intentas reutilizar un nombre ocupado, Docker dará error.
Ejemplo Práctico Completo: Un Servidor Nginx en tu Navegador
Vamos a juntar todo lo anterior en un ejemplo de principio a fin. El objetivo es tener un servidor web Nginx funcionando y verlo en el navegador.
Paso 1: Lanzar el Contenedor
-d: en segundo plano (es un servicio).--name servidor_nginx: nombre legible.-p 8080:80: el puerto 8080 del host apunta al 80 del contenedor.nginx: la imagen oficial de Nginx (se descarga automáticamente si no la tienes).
Paso 2: Comprobar que Está en Marcha
- Deberías ver
servidor_nginxen la lista, con el estadoUp ...y el mapeo de puertos0.0.0.0:8080->80/tcp.
Paso 3: Abrir el Navegador
Abre tu navegador y visita:
Verás la página de bienvenida de Nginx ("Welcome to nginx!"). ¡Acabas de servir una página web desde un contenedor Docker!
Paso 4: Revisar los Registros
Cada vez que recargas la página, Nginx registra la petición. Compruébalo:
- Verás líneas de acceso que reflejan tus visitas desde el navegador. Es una forma estupenda de confirmar que el tráfico está llegando al contenedor.
Paso 5: Entrar en el Contenedor (Opcional)
Puedes inspeccionar el contenedor por dentro mientras corre:
- Una vez dentro, prueba
ls /usr/share/nginx/htmlpara ver dónde Nginx guarda los archivos que sirve. Escribeexitpara salir sin detener el contenedor.
Paso 6: Limpiar
Cuando termines, detén y elimina el contenedor:
docker stop: detiene el contenedor de forma ordenada.docker rm: lo elimina. Como Nginx no guardaba datos importantes, no perdemos nada relevante.
Errores Comunes y Consejos
- No poder acceder en el navegador: la causa más frecuente es haber olvidado
-p, o haber invertido el orden (80:8080en lugar de8080:80). Recuerda:host:contenedor. port is already allocated: el puerto del host (8080) ya lo usa otro proceso o contenedor. Elige otro puerto del host, por ejemplo-p 8081:80.- Reutilizar un nombre ocupado: si ves
name is already in use, elimina el contenedor anterior condocker rmo usa un nombre distinto. - Esperar salida con
-d: en modo detached no verás la salida en pantalla; usadocker logspara consultarla. - El contenedor se detiene al salir con
-it: si entraste con-it ... bashy ese era el proceso principal, al hacerexitel contenedor se para. Es normal; para servicios usa-d. - Consejo: pon siempre
--namea tus contenedores. Gestionarlos por nombre es mucho más cómodo que copiar y pegar IDs.
Ejercicios
Ejercicio 1
Lanza un contenedor de Ubuntu en modo interactivo, comprueba qué sistema operativo corre dentro y sal de él. Indica qué ocurre con el contenedor tras salir.
Ejercicio 2
Levanta un servidor Nginx llamado web_practica accesible en http://localhost:8090 y verifica con un comando que está en ejecución y con el mapeo de puerto correcto.
Ejercicio 3
Tienes web_practica corriendo. Sin detenerlo, entra en él, localiza la carpeta donde Nginx guarda los archivos HTML que sirve y sal. Después, detén y elimina el contenedor.
Soluciones
Solución 1
docker run -it ubuntu bash abre una shell dentro de un contenedor Ubuntu; cat /etc/os-release confirma que el sistema interno es Ubuntu (aunque tu host no lo sea). Al hacer exit, como bash era el proceso principal del contenedor, el contenedor se detiene. Seguirá existiendo (lo verás con docker ps -a) hasta que lo elimines.
Solución 2
docker run -d --name web_practica -p 8090:80 nginx arranca Nginx en segundo plano, con nombre y mapeando el puerto 8090 del host al 80 del contenedor. docker ps muestra el contenedor activo con el mapeo 0.0.0.0:8090->80/tcp. Podrás visitarlo en http://localhost:8090.
Solución 3
docker exec -it web_practica sh
ls /usr/share/nginx/html
exit
docker stop web_practica
docker rm web_practicadocker exec -it web_practica sh entra en el contenedor en marcha; ls /usr/share/nginx/html muestra la carpeta donde Nginx guarda sus archivos HTML; exit sale sin detener el contenedor. Finalmente, docker stop y docker rm detienen y eliminan el contenedor.
Conclusión
En esta lección has creado y gestionado tus primeros contenedores de principio a fin: has usado el modo interactivo -it para explorar un contenedor por dentro, el modo detached -d para ejecutar servicios en segundo plano, el mapeo de puertos -p para acceder desde el navegador y --name para nombrarlos de forma legible. Además, has levantado un servidor Nginx real y lo has visto funcionando en tu navegador. Con esto completas el Módulo 1 y dominas ya el flujo básico de trabajo con Docker.
En el Módulo 2: Trabajando con Imágenes y Contenedores, daremos el siguiente paso empezando por Docker Hub y Repositorios, donde aprenderás a buscar, descargar y compartir imágenes a través del mayor registro público de la comunidad, y a sacar el máximo partido de las imágenes oficiales y de la comunidad.
Docker: De Principiante a Avanzado
Módulo 1: Introducción a Docker
- ¿Qué es Docker?
- Instalando Docker
- Arquitectura de Docker
- Comandos Básicos de Docker
- Entendiendo las Imágenes de Docker
- Creando tu Primer Contenedor Docker
Módulo 2: Trabajando con Imágenes Docker
- Docker Hub y Repositorios
- Construyendo Imágenes Docker
- Conceptos Básicos de Dockerfile
- Gestionando Imágenes Docker
- Etiquetado y Publicación de Imágenes
Módulo 3: Contenedores Docker
- Ejecutando Contenedores
- Ciclo de Vida del Contenedor
- Gestionando Contenedores
- Redes en Docker
- Persistencia de Datos con Volúmenes
Módulo 4: Docker Compose
- Introducción a Docker Compose
- Definiendo Servicios en Docker Compose
- Comandos de Docker Compose
- Aplicaciones Multi-Contenedor
- Variables de Entorno en Docker Compose
Módulo 5: Conceptos Avanzados de Docker
- Profundización en Redes Docker
- Opciones de Almacenamiento Docker
- Mejores Prácticas de Seguridad en Docker
- Optimizando Imágenes Docker
- Registro y Monitoreo en Docker
Módulo 6: Docker en Producción
- CI/CD con Docker
- Orquestando Contenedores con Docker Swarm
- Introducción a Kubernetes
- Desplegando Contenedores Docker en Kubernetes
- Escalado y Balanceo de Carga
