Con el fichero ya escrito, toca dominar la herramienta que lo interpreta. La CLI de Compose tiene unos veinticinco subcomandos, pero el reparto es muy desigual: usarás cinco a diario, otros cinco a menudo y el resto en situaciones concretas.
Esta lección los recorre por familias, siempre sobre el compose.yaml de Aurora Libros de la lección anterior. Presta especial atención a dos parejas que se confunden sin parar: up frente a start, y exec frente a run.
Contenido
- Tabla maestra de subcomandos
up: el comando que reconciliadowny el peligro de-vstart,stop,restart,pause,create- Observación:
ps,logs,top,stats,events - Ejecución puntual:
execfrente arun - Construcción y publicación:
build,pull,push - Escalado local con
--scaley sus límites - Diagnóstico:
configy validación en CI - Selección de ficheros y proyecto:
-f,-p,COMPOSE_FILE - Autocompletado y alias útiles
- Tabla maestra de subcomandos
| Familia | Comando | Qué hace |
|---|---|---|
| Ciclo de vida | up |
Crea o actualiza y arranca todo lo declarado |
down |
Para y elimina contenedores y redes del proyecto | |
create |
Crea los contenedores sin arrancarlos | |
start / stop |
Arranca o para contenedores ya existentes | |
restart |
Para y vuelve a arrancar sin releer el fichero | |
pause / unpause |
Congela y descongela los procesos (SIGSTOP) | |
kill |
Envía una señal (SIGKILL por defecto) | |
rm |
Elimina contenedores parados | |
| Observación | ps |
Estado de los servicios del proyecto |
logs |
Registros agregados por servicio | |
top |
Procesos dentro de cada contenedor | |
stats |
Consumo de recursos en vivo | |
events |
Flujo de eventos del proyecto | |
port |
Puerto del host asociado a un puerto interno | |
| Ejecución | exec |
Comando en un contenedor en marcha |
run |
Comando en un contenedor nuevo | |
| Imágenes | build |
Construye los servicios con build: |
pull / push |
Descarga o publica las imágenes | |
images |
Imágenes usadas por el proyecto | |
| Diagnóstico | config |
Valida y muestra la configuración final |
version |
Versión de Compose | |
ls |
Lista todos los proyectos de la máquina | |
cp |
Copia ficheros entre host y servicio | |
wait |
Bloquea hasta que un servicio termine |
Un comando que se olvida y es utilísimo: docker compose ls funciona desde cualquier directorio y te dice qué proyectos hay levantados en la máquina y con qué fichero.
up: el comando que reconcilia
up: el comando que reconciliadocker compose up es el 80 % del uso diario. No es "arrancar": es llevar el estado real al estado declarado. En cada ejecución, para cada servicio, Compose calcula un resumen de su configuración (el config-hash que viste en la lección 04-01) y decide:
| Situación | Acción de Compose |
|---|---|
| El contenedor no existe | Lo crea y lo arranca |
| Existe y la configuración coincide | No lo toca |
| Existe pero cambió el fichero o la imagen | Lo recrea |
| Existe pero está parado | Lo arranca |
| Existe y no está en el fichero | Lo deja (salvo --remove-orphans) |
Esa selectividad es lo que hace que editar la memoria de la caché y ejecutar up -d recree solo la caché y no tire abajo la base de datos.
| Opción | Efecto |
|---|---|
-d, --detach |
En segundo plano. En la práctica, siempre |
--build |
Construye antes de arrancar los servicios con build: |
--no-build |
Falla si falta una imagen en lugar de construir |
--pull always |
Descarga la imagen aunque exista en local |
--force-recreate |
Recrea todo aunque nada haya cambiado |
--no-recreate |
No recrea nada aunque haya cambiado |
--no-deps |
Ignora depends_on: solo el servicio pedido |
--wait |
Espera a que los servicios estén healthy antes de devolver el control |
--wait-timeout 60 |
Segundos máximos de espera de --wait |
--remove-orphans |
Elimina contenedores del proyecto que ya no están en el fichero |
--abort-on-container-exit |
Para todo si un contenedor termina (útil en CI) |
--scale s=N |
Arranca N réplicas del servicio s |
[+] Building 2/2
[+] Running 4/4
✔ Container aurora-libros-aurora-db-1 Healthy
✔ Container aurora-libros-aurora-cache-1 Healthy
✔ Container aurora-libros-aurora-api-1 Healthy
✔ Container aurora-libros-aurora-web-1 Healthy--wait es la opción que convierte a Compose en una herramienta de automatización: sin ella, el comando devuelve el control en cuanto los contenedores están arrancados, y un script de CI que lanza pruebas inmediatamente después se estrella contra una base de datos que aún no acepta conexiones. Con --wait, Compose no devuelve el control hasta que todas las sondas de salud pasan, y sale con código distinto de cero si alguna no lo consigue.
Sin -d, up deja el terminal enganchado a los logs agregados de todos los servicios y Ctrl+C para la pila entera. Es cómodo para depurar un arranque; peligroso si lo olvidas en una sesión SSH.
Un caso muy útil de --no-deps: recrear solo la API sin reiniciar la base de datos.
down y el peligro de -v
down y el peligro de -vdown es la inversa de up: para y elimina contenedores y redes del proyecto.
| Comando | Contenedores | Redes | Volúmenes con nombre | Volúmenes anónimos | Imágenes |
|---|---|---|---|---|---|
down |
Elimina | Elimina | Conserva | Elimina | Conserva |
down -v |
Elimina | Elimina | BORRA | Elimina | Conserva |
down --rmi local |
Elimina | Elimina | Conserva | Elimina | Borra las sin etiqueta propia |
down --rmi all |
Elimina | Elimina | Conserva | Elimina | Borra todas las del proyecto |
down --remove-orphans |
Elimina también los huérfanos | Elimina | Conserva | Elimina | Conserva |
stop |
Conserva (parados) | Conserva | Conserva | Conserva | Conserva |
Grábate la segunda fila. docker compose down -v borra los volúmenes con nombre del proyecto sin preguntar: en Aurora Libros, eso es el catálogo entero de la librería. Es exactamente lo que quieres al resetear un entorno de desarrollo y exactamente lo que arruina un servidor si lo tecleas por inercia. Dos defensas: declarar los volúmenes críticos como external: true (lección 04-02) y no crear jamás un alias de shell que incluya -v.
start, stop, restart, pause, create
start, stop, restart, pause, create| Comando | ¿Lee el fichero? | ¿Recrea? | Cuándo usarlo |
|---|---|---|---|
up -d |
Sí | Si hay cambios | Siempre que toques el compose.yaml |
start |
No | Nunca | Volver a arrancar lo ya creado |
stop |
No | No | Parar sin destruir |
restart |
No | No | Reiniciar el proceso, sin aplicar cambios |
pause |
No | No | Congelar procesos liberando CPU, no memoria |
create |
Sí | Si hay cambios | Crear sin arrancar |
La trampa de restart merece un aviso explícito: no relee el fichero. Si cambias una variable de entorno y ejecutas docker compose restart aurora-api, el contenedor se reinicia con la configuración antigua y te vuelves loco buscando por qué no se aplica el cambio. Para aplicar cambios del fichero, siempre up -d.
docker compose stop aurora-cache # parar un servicio concreto
docker compose start aurora-cache # volver a arrancarlo
docker compose restart aurora-web # reinicio rápido de nginx
docker compose kill -s SIGHUP aurora-web # recargar configuración sin reiniciar
- Observación:
ps, logs, top, stats, events
ps, logs, top, stats, eventsdocker compose ps
docker compose ps -a # incluye los parados y los que terminaron
docker compose ps --services # solo nombres de servicio, uno por línea
docker compose ps --status running
docker compose ps --format "table {{.Service}}\t{{.Status}}\t{{.Ports}}"
docker compose ps --format json | jq -r '.[] | "\(.Service): \(.Health)"'--services es oro para guiones: for s in $(docker compose ps --services); do ...; done.
Los logs son la herramienta que más usarás:
docker compose logs # todos los servicios, agregados
docker compose logs -f aurora-api # seguir uno en tiempo real
docker compose logs --tail 50 aurora-db # últimas 50 líneas
docker compose logs --since 10m # de los últimos 10 minutos
docker compose logs -t --no-color api web # con marca de tiempo, varios serviciosCompose colorea y prefija cada línea con el nombre del servicio, así que docker compose logs -f con la pila entera te deja ver el flujo de una petición atravesando web → api → db. Recuerda de la lección 03-04 que solo verás lo que los procesos escriban en stdout/stderr.
docker compose top aurora-db # procesos dentro del contenedor
docker compose stats --no-stream # consumo puntual de todos los servicios
docker compose events --json # flujo de eventos del proyecto
docker compose port aurora-web 80port responde a "¿en qué puerto del host está publicado el 80 de la web?", y es imprescindible cuando dejas que Docker asigne puertos aleatorios.
- Ejecución puntual:
exec frente a run
exec frente a runEs la distinción que más confusión genera, y la respuesta es simple: exec entra en un contenedor que ya está corriendo; run crea uno nuevo.
| Aspecto | exec |
run |
|---|---|---|
| Contenedor | El existente del servicio | Uno nuevo, con sufijo -run-<hash> |
| Requisito | El servicio debe estar en marcha | El servicio no necesita estar arrancado |
| Dependencias | Irrelevante | Arranca las de depends_on (evítalo con --no-deps) |
| Puertos | Los que ya tiene | No publica los ports (salvo --service-ports) |
| Al terminar | El contenedor sigue vivo | Queda parado, salvo --rm |
| Uso típico | Inspeccionar, psql, redis-cli, shell |
Tareas puntuales: migraciones, pruebas, seeds |
# EXEC: hablar con la base de datos que está sirviendo ahora mismo
docker compose exec aurora-db psql -U aurora -d aurora_libros
docker compose exec aurora-db psql -U aurora -d aurora_libros -c "SELECT count(*) FROM libros;"
docker compose exec aurora-cache redis-cli INFO keyspace
docker compose exec aurora-api sh # shell dentro de la API
docker compose exec -u root aurora-api sh # como root, para instalar algo
docker compose exec -T aurora-db pg_dump -U aurora aurora_libros > copia.sql-T desactiva la asignación de pseudo-TTY: obligatorio cuando rediriges la salida a un fichero o encadenas tuberías, o el volcado saldrá con caracteres de control.
# RUN: contenedores nuevos y efímeros
docker compose run --rm aurora-api npm test
docker compose run --rm --no-deps aurora-api node -e "console.log(process.version)"
docker compose run --rm --entrypoint sh aurora-api
docker compose run --rm -e NODE_ENV=test aurora-api npm run test:integracion
docker compose run --rm --service-ports aurora-api # publica sus puertos> [email protected] test
> node --test
✔ GET /salud devuelve 200 (12.4ms)
✔ GET /libros devuelve 9 títulos (31.7ms)
✔ GET /libros/:id inexistente devuelve 404 (4.1ms)
ℹ pass 3--rm casi siempre. Sin él, cada run deja un contenedor parado en la máquina; al cabo de una semana tienes cuarenta contenedores aurora-libros-aurora-api-run-a3f9c2 ocupando espacio. Y --no-deps cuando la tarea no necesita la pila: sin él, un run inocente te levanta PostgreSQL y Redis.
- Construcción y publicación:
build, pull, push
build, pull, pushdocker compose build # construye los servicios con build:
docker compose build --no-cache aurora-api # ignora la caché de capas
docker compose build --pull # refresca la imagen base primero
docker compose build --progress plain # salida completa, útil para depurar
docker compose pull # descarga las imágenes declaradas
docker compose pull --ignore-buildable # omite los servicios que se construyen
docker compose push aurora-api # publica en el registro
docker compose imagesCONTAINER REPOSITORY TAG SIZE
aurora-libros-aurora-api-1 auroralibros/aurora-api 1.2.0 142MB
aurora-libros-aurora-cache-1 redis 7-alpine 41.4MB
aurora-libros-aurora-db-1 postgres 16-alpine 274MB
aurora-libros-aurora-web-1 nginx alpine 48.3MBEl flujo típico de CI, que verás completo en la lección 06-02, cabe en tres líneas: docker compose build, docker compose push y, en el servidor, docker compose pull && docker compose up -d.
- Escalado local con
--scale y sus límites
--scale y sus límitesError response from daemon: driver failed programming external connectivity:
Bind for 0.0.0.0:3000 failed: port is already allocatedAhí está el primer choque: un puerto fijo del host no se puede repartir entre tres réplicas. Solo hay un 3000 en la máquina. Y si el servicio tuviera container_name, fallaría antes todavía, porque dos contenedores no pueden llamarse igual.
| Obstáculo | Por qué choca | Solución |
|---|---|---|
ports: ["3000:3000"] |
Un solo puerto del host | Quitar el puerto o usar - "3000" (aleatorio) |
container_name |
Nombres duplicados | No usar container_name |
| Volumen de datos compartido | Dos Postgres sobre los mismos ficheros | No escalar servicios con estado |
Quitando la publicación fija, funciona:
docker compose up -d --scale aurora-api=3
docker compose ps --services --filter status=running | sort | uniq -c
docker compose exec aurora-web getent hosts aurora-apiEl DNS interno de Docker devuelve las tres direcciones para el mismo nombre, y el cliente elige una. Es un reparto rudimentario —sin comprobación de salud, sin pesos, sin reintentos— que sirve para pruebas locales, no para producción. El balanceo real, con sus estrategias y su gestión de réplicas caídas, es la lección 06-06.
- Diagnóstico:
config y validación en CI
config y validación en CIdocker compose config lee todos los ficheros implicados, interpola variables, fusiona overrides y muestra la configuración final tal y como la entiende Compose. Es tu única forma de ver la verdad.
docker compose config # configuración completa resuelta
docker compose config --quiet # solo valida: sin salida, código 0 o 1
docker compose config --services # nombres de los servicios
docker compose config --volumes # nombres de los volúmenes
docker compose config --images # imágenes que se usarán
docker compose config --no-interpolate # deja los ${...} sin resolver
docker compose config --format json | jq '.services["aurora-api"].deploy'En una tubería de CI, --quiet es la primera comprobación que debe correr, antes incluso de construir nada:
Dos avisos sobre config: resuelve las variables, así que su salida puede contener contraseñas en claro (nunca la vuelques en un log público), y muestra el resultado normalizado, con las formas cortas convertidas en formas largas. Esa normalización es justo lo que necesitas para entender qué hizo una fusión de anclas o de ficheros.
- Selección de ficheros y proyecto:
-f, -p, COMPOSE_FILE
-f, -p, COMPOSE_FILELas opciones globales van antes del subcomando:
docker compose -f ~/aurora-libros/compose.yaml ps # correcto
docker compose ps -f ~/aurora-libros/compose.yaml # ERROR| Opción | Qué hace |
|---|---|
-f, --file |
Fichero a usar. Repetible, y el orden importa |
-p, --project-name |
Nombre del proyecto (prefijo de todos los objetos) |
--project-directory |
Directorio base para resolver rutas relativas |
--profile |
Activa un perfil (lección 04-06) |
--env-file |
Fichero de variables para la interpolación (lección 04-05) |
Con varios -f, Compose fusiona los ficheros en el orden dado y el último gana en caso de conflicto. El mecanismo de fusión completo, con sus reglas por tipo de clave, es la lección 04-06.
Un detalle que sorprende: cuando usas -f, el directorio base para las rutas relativas pasa a ser el del primer fichero. Si tus ficheros están repartidos, --project-directory te deja fijarlo explícitamente.
Y la variable de entorno equivalente, útil para no repetir -f cien veces al día:
export COMPOSE_FILE=compose.yaml:compose.prod.yaml # separador ":" en Linux/macOS
export COMPOSE_PROJECT_NAME=aurora-prod
docker compose up -d # usa ambos ficheros y el nombre de proyecto
- Autocompletado y alias útiles
# Bash: completado de subcomandos, servicios y opciones
docker completion bash | sudo tee /etc/bash_completion.d/docker > /dev/null
# Zsh
docker completion zsh > "${fpath[1]}/_docker"Con el autocompletado activo, docker compose logs -f aur<TAB> te ofrece los servicios reales del proyecto: se acabó teclear mal los nombres.
alias dc='docker compose'
alias dcu='docker compose up -d'
alias dcl='docker compose logs -f --tail 100'
alias dcp='docker compose ps'
alias dce='docker compose exec'
# Deliberadamente NO existe un alias con "down -v"Ese último comentario no es una broma: la mayor parte de las pérdidas de datos con Compose vienen de un alias corto que alguien escribió con -v "para limpiar rápido".
Errores Comunes y Consejos
Usar restart esperando que aplique cambios del fichero. No lo hace. Cambio en el compose.yaml → up -d, siempre.
Confundir stop con down. stop conserva los contenedores, down los elimina junto con la red. Si tras un down esperabas encontrar el contenedor parado, no está.
Teclear down -v por costumbre. Borra los volúmenes con nombre y con ellos los datos. Piénsalo cada vez.
Olvidar --rm en run. Cada ejecución deja un contenedor parado. Limpia los acumulados con docker compose rm -f.
Ejecutar exec con redirección sin -T. El pseudo-TTY inserta caracteres de control y corrompe volcados y ficheros binarios.
Poner -f después del subcomando. Las opciones globales van antes; el error que devuelve la CLI no siempre lo deja claro.
Consejo: cuando algo no se comporta como esperas, el orden de diagnóstico es docker compose config (¿qué entiende Compose?), docker compose ps (¿qué está corriendo?) y docker compose logs (¿qué dice el servicio?). En ese orden resuelves casi todo.
Ejercicios
Ejercicio 1. Con la pila levantada, cambia el límite de memoria de aurora-cache de 256M a 320M y aplícalo sin que se reinicien los otros tres servicios. Demuestra con comandos que solo se recreó la caché y que el límite nuevo está activo.
Ejercicio 2. Escribe un guion verificar.sh apto para CI que: valide el fichero, levante la pila esperando a que esté sana, ejecute las pruebas de la API en un contenedor efímero, imprima el estado de los cuatro servicios y limpie todo, volúmenes incluidos, devolviendo el código de salida de las pruebas.
Ejercicio 3. Sin apagar la pila, obtén: (a) el número de claves en Redis, (b) los tres primeros títulos del catálogo ordenados alfabéticamente, y (c) un volcado de la tabla libros en el fichero ~/libros.sql del host. Explica qué opción es imprescindible en el tercer caso y por qué.
Soluciones
Solución 1.
aurora-api: 22 minutes ago
aurora-cache: 22 minutes ago
aurora-db: 22 minutes ago
aurora-web: 22 minutes agoEdita el límite en el compose.yaml (limits: { memory: 320M, cpus: "0.5", pids: 100 }) y aplica:
✔ Container aurora-libros-aurora-db-1 Running
✔ Container aurora-libros-aurora-cache-1 Recreated
✔ Container aurora-libros-aurora-api-1 Running
✔ Container aurora-libros-aurora-web-1 RunningAhí está la reconciliación: Recreated solo en la caché, Running en los otros tres porque su config-hash no cambió. Verificación:
docker compose ps --format "{{.Service}}: {{.RunningFor}}"
docker inspect aurora-libros-aurora-cache-1 --format '{{.HostConfig.Memory}}'La caché lleva cuatro segundos y los demás siguen con sus veintidós minutos. Y 335544320 bytes son exactamente 320 MiB. Ojo: recrear un contenedor no es reiniciarlo, es destruirlo y crear otro; los datos que no estén en un volumen se pierden. En Redis, eso significa una caché vacía, que aquí es inocuo porque /libros la repuebla desde la base de datos.
Solución 2.
#!/usr/bin/env bash
# verificar.sh — pipeline local de Aurora Libros
set -uo pipefail
cd "$(dirname "$0")"
docker compose config --quiet || { echo "compose.yaml inválido"; exit 1; }
docker compose up -d --build --wait --wait-timeout 90 || {
echo "La pila no llegó a estado sano"
docker compose logs --tail 40
docker compose down -v
exit 1
}
docker compose run --rm --no-deps aurora-api npm test
codigo=$?
docker compose ps --format "table {{.Service}}\t{{.Status}}"
docker compose down -v --remove-orphans
exit $codigoCuatro decisiones importantes: --quiet valida antes de gastar tiempo construyendo; --wait con --wait-timeout garantiza que las pruebas no arranquen contra una base de datos que aún no responde y falla con código distinto de cero si no lo consigue; --rm --no-deps en las pruebas evita dejar basura y no vuelve a levantar dependencias que ya están sanas; y down -v es aquí correcto y deseable, porque es un entorno desechable. Fíjate en que se guarda $? antes de los comandos de limpieza: si no, el código de salida que devuelve el guion sería el de down, y el pipeline pasaría siempre en verde.
Solución 3.
# (a) claves en la caché
docker compose exec aurora-cache redis-cli DBSIZE
# (b) tres primeros títulos
docker compose exec aurora-db psql -U aurora -d aurora_libros \
-c "SELECT titulo FROM libros ORDER BY titulo LIMIT 3;"
# (c) volcado al host
docker compose exec -T aurora-db pg_dump -U aurora -t libros aurora_libros > ~/libros.sql(integer) 1
titulo
------------------------------------------
Cien años de soledad
El Aleph
El jardín de senderos que se bifurcan
(3 rows)En el tercer caso -T es imprescindible. Sin él, Compose asigna un pseudo-TTY al comando y el flujo de salida deja de ser binario limpio: se traducen los saltos de línea y se cuelan secuencias de control, con lo que el .sql resultante puede no volver a importarse. La regla es sencilla: si la salida no la vas a leer tú con los ojos, -T.
Conclusión
Ya manejas la CLI completa. Sabes que up no es "arrancar" sino "reconciliar": compara el resumen de configuración de cada servicio con el declarado y recrea solo lo que cambió, lo que te permite ajustar un límite y tocar un único contenedor. Conoces sus opciones decisivas —-d, --build, --pull, --force-recreate, --no-deps, --remove-orphans y sobre todo --wait, que espera a que las sondas de salud pasen y falla si no lo hacen—. Y tienes claro qué borra cada variante de down, con -v marcado en rojo.
Distingues start/stop/restart/pause de up/down, con la trampa de que restart no relee el fichero. Observas con ps (incluidos --services y --format json), logs, top, stats, events y port. Y tienes interiorizada la diferencia clave: exec entra en lo que ya corre, run crea un contenedor nuevo, con --rm para no acumular basura, --no-deps para no levantar media pila y -T cuando rediriges la salida. Construyes y publicas con build/pull/push, escalas localmente con --scale sabiendo que choca con los puertos fijos y con container_name, validas con config --quiet en CI y controlas qué fichero y qué proyecto usas con -f, -p y COMPOSE_FILE.
En la lección siguiente, Aplicaciones Multi-Contenedor, todo esto se pone al servicio del montaje definitivo: la arquitectura de Aurora Libros con dos redes segmentadas —una frontal y una trasera marcada como internal—, el DNS de Compose y la tabla de quién habla con quién y por qué puerto, el orden de arranque resuelto con depends_on y condition: service_healthy usando pg_isready y redis-cli ping, un servicio de migración con service_completed_successfully, y el patrón de reintento con backoff que hace falta aunque tengas todo lo anterior. Al final, los quince pasos de onboarding se quedarán en dos.
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
- El Proyecto del Curso: la Plataforma Aurora Libros
Módulo 2: Trabajando con Imágenes Docker
- Docker Hub y Repositorios
- Construyendo Imágenes Docker
- Conceptos Básicos de Dockerfile
- Instrucciones Avanzadas del 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
- Inspección y Depuración de Contenedores
- Redes en Docker
- Persistencia de Datos con Volúmenes
- Límites de Recursos y Políticas de Reinicio
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
- Perfiles, Overrides y Múltiples Entornos
- Desarrollo Local con 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
- Builds Avanzadas con BuildKit y Buildx
- Registro y Monitoreo en Docker
- El Runtime por Dentro: Namespaces, Cgroups y Capas
Módulo 6: Docker en Producción
- Preparar una Imagen para 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
- Estrategias de Despliegue y Rollback
