Tu compose.yaml de la lección anterior usa siete claves. La especificación de Compose define más de sesenta, pero no necesitas memorizarlas: la mayoría son la traducción directa de una opción de docker run que ya dominas del módulo 3.
Esta lección es la referencia práctica de un servicio, organizada por bloques y aplicada a Aurora Libros. Al final tendrás los cuatro servicios declarados en un solo fichero. La explicación de cómo interactúan entre sí es la lección 04-04, y las variables de entorno tienen lección propia, la 04-05.
Contenido
- Tabla maestra: claves de servicio y su equivalente en
docker run - Imagen y construcción:
imageybuild - Identidad:
container_nameyhostname - Ejecución:
command,entrypoint,user,inity el apagado - Red y puertos:
ports,expose,networks, alias - Datos:
volumes,tmpfs,read_only - Salud y dependencias:
healthcheckydepends_on - Recursos y reinicio:
restartydeploy.resources - Etiquetas:
labels - Bloques de nivel superior:
volumes:ynetworks: - Anclas y referencias YAML para no repetirse
- Aurora Libros: los cuatro servicios declarados
- Tabla maestra: claves de servicio y su equivalente en
docker run
docker run| Clave de Compose | Opción de docker run |
Para qué sirve |
|---|---|---|
image |
argumento final | Imagen de la que parte el contenedor |
build |
docker build aparte |
Construir la imagen desde un Dockerfile |
container_name / hostname |
--name / --hostname |
Nombre del contenedor y nombre de host interno |
command / entrypoint |
argumentos tras la imagen / --entrypoint |
Sustituyen al CMD y al ENTRYPOINT de la imagen |
user / working_dir |
-u / -w |
UID:GID del proceso y directorio de trabajo |
init |
--init |
Inserta tini como PID 1 |
stop_signal / stop_grace_period |
--stop-signal / --stop-timeout |
Señal de apagado y margen antes de SIGKILL |
environment / env_file |
-e / --env-file |
Variables dentro del contenedor |
ports |
-p |
Publicar puertos en el host |
expose |
--expose |
Documentar puertos internos |
networks |
--network |
Redes a las que se conecta |
volumes |
-v / --mount |
Montajes de datos |
tmpfs / read_only |
--tmpfs / --read-only |
Ficheros en RAM y raíz inmutable |
healthcheck |
--health-* |
Sonda de salud |
depends_on |
(no existe) | Orden de arranque entre servicios |
restart |
--restart |
Política de reinicio |
deploy.resources.limits |
--memory, --cpus |
Límites de recursos |
labels |
--label |
Metadatos |
cap_add / cap_drop |
--cap-add / --cap-drop |
Capacidades del kernel |
extra_hosts |
--add-host |
Entradas en /etc/hosts |
La única fila sin equivalente es depends_on, y no es casualidad: la relación entre servicios es exactamente lo que docker run no sabe expresar.
- Imagen y construcción:
image y build
image y buildimage toma una referencia igual que docker run: repositorio y etiqueta (postgres:16-alpine) o, mejor para producción, un digest inmutable (postgres@sha256:9f3d0e...).
build le dice a Compose que construya la imagen en lugar de descargarla. En forma corta es solo el contexto (build: ./api); en forma larga, todo lo que aprendiste en el módulo 2:
build:
context: ./api # directorio del contexto de build
dockerfile: Dockerfile # relativo al contexto
args: { NODE_VERSION: "22" } # valores para las instrucciones ARG
target: produccion # etapa concreta en builds multietapa
cache_from: ["auroralibros/aurora-api:cache"]
image: auroralibros/aurora-api:1.2.0 # nombre con el que se etiquetaCuando aparecen las dos claves juntas, build manda al construir e image da el nombre del resultado. Es la combinación más útil: docker compose build etiqueta la imagen con ese nombre y docker compose push la publica.
| Situación | Usa | Motivo |
|---|---|---|
| Servicio de terceros (Postgres, Redis, Nginx) | image |
No tienes su código |
| Desarrollo de tu propio código | build (+ image) |
Reconstruyes al cambiar |
| Producción | image con etiqueta inmutable |
Despliegas lo mismo que probaste |
| CI que construye y publica | Ambas | build + push con un nombre fijo |
Con solo build, si no pones image, Compose etiqueta la imagen como <proyecto>-<servicio>.
- Identidad:
container_name y hostname
container_name y hostname container_name: aurora-db # casi siempre: NO lo pongas
hostname: aurora-db # nombre que devuelve `hostname` dentrocontainer_name fija el nombre exacto y desactiva el prefijado de proyecto. Suena cómodo, y por eso mucha gente lo pone; tiene tres inconvenientes serios: impide docker compose up --scale (dos contenedores no pueden llamarse igual), impide levantar dos proyectos del mismo fichero en la misma máquina, y no lo necesitas, porque para hablar entre servicios se usa el nombre del servicio. Ponlo solo cuando algo externo —un script heredado, un agente de monitorización— exija un nombre concreto.
- Ejecución:
command, entrypoint, user y el apagado
command, entrypoint, user y el apagado entrypoint: ["/usr/local/bin/arranque.sh"] # sustituye al ENTRYPOINT
command: ["node", "server.js"] # sustituye al CMD
user: "1001:1001" # UID:GID sin privilegios
working_dir: /app
init: true # tini como PID 1
stop_signal: SIGQUIT # nginx apaga ordenado con esta
stop_grace_period: 30s # margen antes de SIGKILLcommand y entrypoint admiten forma de cadena (command: node server.js, que pasa por el shell) y forma de lista (["node", "server.js"], ejecución directa). Prefiere la lista: es la forma exec y garantiza que tu proceso sea PID 1 y reciba SIGTERM, tal como viste en la lección 03-02. init: true inserta un init mínimo como PID 1 que reenvía señales y entierra zombis, útil cuando tu proceso lanza hijos y no los limpia. Y stop_grace_period acepta unidades (10s, 1m30s): para PostgreSQL, que necesita cerrar un checkpoint antes de morir, súbelo a 30 segundos.
- Red y puertos:
ports, expose, networks, alias
ports, expose, networks, aliasports publica un puerto del contenedor en el host. Forma corta, "[IP:]hostPort:contenedorPort[/protocolo]":
ports:
- "8080:80" # todas las interfaces del host
- "127.0.0.1:5432:5432" # solo localhost
- "3000" # puerto aleatorio del host → 3000
- "5514:514/udp" # protocolo explícitoLa forma larga es más verbosa pero explícita: - {target: 80, published: "8080", protocol: tcp, mode: host}, donde target es el puerto interno, published el del host y mode: ingress solo tiene sentido en Swarm.
expose no publica nada: documenta qué puertos escucha el contenedor. Es informativo, porque dentro de una red de usuario todos los puertos entre contenedores ya son accesibles.
networks conecta el servicio a las redes declaradas en el bloque de nivel superior. Sin esta clave, el servicio va a la red default del proyecto.
Un servicio puede estar en varias redes a la vez —es exactamente lo que hará aurora-api en la lección 04-04— y los aliases le dan nombres DNS extra, útiles para migrar sin tocar el código de los clientes.
- Datos:
volumes, tmpfs, read_only
volumes, tmpfs, read_onlyLa forma corta es la sintaxis origen:destino[:opciones] de docker run -v, y el origen decide el tipo de montaje:
volumes:
- aurora-datos:/var/lib/postgresql/data # volumen con nombre
- ./db/init.sql:/docker-entrypoint-initdb.d/init.sql:ro # bind (empieza por ./)
- /app/node_modules # volumen anónimoLa regla es la del módulo 3: si el origen empieza por . o / es un bind mount; si no, es un volumen con nombre que debe declararse en el bloque volumes: de nivel superior. La forma larga equivale a --mount:
volumes:
- type: volume
source: aurora-datos
target: /var/lib/postgresql/data
- type: bind
source: ./db/init.sql
target: /docker-entrypoint-initdb.d/init.sql
read_only: true
- type: tmpfs
target: /tmp
tmpfs: { size: 67108864 } # 64 MB, en bytesUna diferencia importante: con la forma corta, si el origen de un bind no existe, Docker crea un directorio vacío; con la forma larga, falla con un error claro y te ahorra el clásico "monté un directorio donde esperaba un fichero".
read_only: true # raíz del contenedor inmutable
tmpfs: [/tmp, /run] # lo poco que sí necesita escribirread_only: true con un par de tmpfs es una de las medidas de endurecimiento más baratas que existen; el tema completo es la lección 05-03.
- Salud y dependencias:
healthcheck y depends_on
healthcheck y depends_onEl healthcheck de Compose sustituye o complementa al HEALTHCHECK del Dockerfile:
healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://localhost:3000/salud"]
interval: 10s # cada cuánto se ejecuta
timeout: 3s # cuánto espera la respuesta
retries: 3 # fallos seguidos antes de marcar unhealthy
start_period: 20s # gracia inicial: los fallos aquí no cuentan
start_interval: 2s # sondeo más frecuente durante start_periodTres formas de escribir test:
| Forma | Ejemplo | Cómo se ejecuta |
|---|---|---|
CMD |
["CMD", "pg_isready", "-U", "aurora"] |
Directa, sin shell |
CMD-SHELL |
["CMD-SHELL", "curl -f localhost/salud || exit 1"] |
Con /bin/sh -c: admite tuberías y || |
| Cadena | test: pg_isready -U aurora |
Equivale a CMD-SHELL |
| Desactivar | test: ["NONE"] |
Anula el HEALTHCHECK de la imagen |
start_period es la clave que casi nadie usa y casi todo el mundo necesita: PostgreSQL tarda unos segundos en aceptar conexiones la primera vez, y sin ese margen el contenedor se marca unhealthy antes de haber tenido oportunidad de arrancar.
depends_on en forma corta —depends_on: [aurora-db, aurora-cache]— solo garantiza el orden de arranque: Compose lanza el contenedor de PostgreSQL, espera a que el proceso esté en marcha y acto seguido lanza la API. Pero PostgreSQL tarda cinco segundos más en aceptar conexiones, así que la API arranca contra una base de datos que aún no responde. La forma larga resuelve exactamente eso:
depends_on:
aurora-db:
condition: service_healthy # espera a que el healthcheck pase
restart: true # reinicia este servicio si la dependencia se recrea
aurora-cache:
condition: service_started # basta con que esté arrancado
aurora-migraciones:
condition: service_completed_successfully # espera a que termine con código 0| Condición | Espera a que la dependencia... | Requiere |
|---|---|---|
service_started |
Esté en marcha (equivale a la forma corta) | Nada |
service_healthy |
Pase su sonda de salud | Un healthcheck definido |
service_completed_successfully |
Termine con código de salida 0 | Un servicio de un solo uso |
La distinción entre "arrancado" y "listo" es la que separa un compose.yaml que funciona en tu máquina de uno que funciona siempre. Se desarrolla en la lección 04-04.
- Recursos y reinicio:
restart y deploy.resources
restart y deploy.resourcesrestart acepta los cuatro valores de docker run con el mismo significado: no (por defecto), always, on-failure[:n] y unless-stopped. Los límites, en cambio, viven bajo deploy, un bloque que originalmente era exclusivo de Swarm:
deploy:
resources:
limits:
memory: 512M # equivale a --memory 512m
cpus: "1.0" # equivale a --cpus 1.0
pids: 200 # equivale a --pids-limit 200
reservations:
memory: 256M # garantía mínima (equivale a --memory-reservation)
cpus: "0.25"Aquí hay una confusión clásica que conviene aclarar: fuera de Swarm, docker compose sí aplica deploy.resources.limits. Lo que se ignora son replicas, placement, update_config y rollback_config, porque no tienen sentido en un solo host. Y recuerda de la lección 03-07 que limits es un techo duro —superar el de memoria significa OOM y código 137— mientras que reservations es una garantía blanda que influye en quién cede memoria bajo presión.
- Etiquetas:
labels
labelsAdmite también forma de lista (- "clave=valor"). Usa la notación de DNS inverso en las claves para no chocar con las de otras herramientas. Sirven para filtrar (docker ps --filter "label=..."), y muchas herramientas del ecosistema —proxies inversos automáticos, agentes de métricas— se configuran exclusivamente con etiquetas.
- Bloques de nivel superior:
volumes: y networks:
volumes: y networks:Todo volumen con nombre que uses en un servicio debe declararse arriba:
volumes:
aurora-datos: # lo más habitual: driver local por defecto
aurora-copias:
name: copias-aurora-libros # nombre exacto, SIN prefijo de proyecto
labels: { com.auroralibros.retencion: "30d" }
aurora-compartido:
external: true # ya existe; Compose no lo crea ni lo borra
aurora-nfs:
driver: local
driver_opts: # opciones que se pasan al driver
{ type: nfs, o: "addr=10.0.0.20,rw,nfsvers=4", device: ":/exports/aurora" }external: true es la protección definitiva para datos críticos: Compose asume que el volumen existe y ni siquiera down -v lo toca. Si no existe, el up falla en lugar de crear uno vacío en silencio.
Las redes siguen el mismo patrón:
networks:
frontal:
driver: bridge
trasera:
driver: bridge
internal: true # sin acceso a Internet ni al exterior
labels: { com.auroralibros.zona: "datos" }
externa:
external: true
name: aurora-net # una red creada fuera de Composeinternal: true es la clave que sostiene la segmentación de la lección 04-04: los contenedores de esa red no tienen ruta hacia el exterior, ni el exterior hacia ellos. Una base de datos ahí dentro no puede descargar nada de Internet aunque alguien logre ejecutar código en ella.
- Anclas y referencias YAML para no repetirse
Cuando cuatro servicios comparten política de reinicio, logging y etiquetas, copiarlo cuatro veces es pedir que se desincronicen. YAML ofrece anclas (&), referencias (*) y fusión de mapas (<<:), y Compose añade las claves de extensión x-, que ignora al procesar el fichero:
x-comun: &comun # define el ancla "comun"
restart: unless-stopped
logging:
driver: json-file
options: { max-size: "10m", max-file: "3" }
x-sonda-rapida: &sonda-rapida
{ interval: 10s, timeout: 3s, retries: 3, start_period: 20s }
services:
aurora-cache:
<<: *comun # fusiona todo el contenido del ancla
image: redis:7-alpine
healthcheck:
<<: *sonda-rapida # las anclas también valen para sub-bloques
test: ["CMD", "redis-cli", "ping"]
aurora-web:
<<: *comun
image: nginx:alpine
restart: always # las claves locales GANAN a las fusionadasDos límites que conviene conocer: las anclas solo funcionan dentro del mismo fichero (no cruzan varios -f), y <<: fusiona al primer nivel, no en profundidad: si el ancla trae labels y el servicio también define labels, el del servicio sustituye al del ancla por completo, no los mezcla. Comprueba siempre el resultado con docker compose config.
- Aurora Libros: los cuatro servicios declarados
Con todo lo anterior, este es el fichero completo. Las credenciales siguen escritas a mano —eso se arregla en la lección 04-05— y hay una sola red; la segmentación llega en la 04-04.
# compose.yaml — Aurora Libros S.L.
name: aurora-libros
x-comun: &comun
restart: unless-stopped
logging:
driver: json-file
options: { max-size: "10m", max-file: "3" }
labels:
com.auroralibros.proyecto: "aurora-libros"
x-sonda: &sonda
{ interval: 10s, timeout: 3s, retries: 3, start_period: 20s }
services:
aurora-db:
<<: *comun
image: postgres:16-alpine
environment:
POSTGRES_USER: aurora
POSTGRES_PASSWORD: aurora_secreta
POSTGRES_DB: aurora_libros
ports:
- "127.0.0.1:5432:5432"
volumes:
- aurora-datos:/var/lib/postgresql/data
- ./db/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
healthcheck:
<<: *sonda
test: ["CMD-SHELL", "pg_isready -U aurora -d aurora_libros"]
start_period: 30s # la primera inicialización tarda más
stop_grace_period: 30s
deploy:
resources:
limits: { memory: 512M, cpus: "1.0", pids: 200 }
reservations: { memory: 256M }
networks: [aurora-net]
aurora-cache:
<<: *comun
image: redis:7-alpine
command: ["redis-server", "--maxmemory", "200mb", "--maxmemory-policy", "allkeys-lru"]
healthcheck:
<<: *sonda
test: ["CMD", "redis-cli", "ping"]
deploy:
resources:
limits: { memory: 256M, cpus: "0.5", pids: 100 }
networks: [aurora-net]
aurora-api:
<<: *comun
build:
context: ./api
dockerfile: Dockerfile
image: auroralibros/aurora-api:1.2.0
environment:
PORT: "3000"
DB_HOST: aurora-db
DB_USER: aurora
DB_PASSWORD: aurora_secreta
DB_NAME: aurora_libros
REDIS_HOST: aurora-cache
ports:
- "3000:3000" # solo para pruebas directas contra la API
healthcheck:
<<: *sonda
test: ["CMD", "wget", "--spider", "-q", "http://localhost:3000/salud"]
restart: on-failure:3 # sobrescribe el unless-stopped del ancla
deploy:
resources:
limits: { memory: 256M, cpus: "1.0", pids: 100 }
reservations: { memory: 128M }
networks: [aurora-net]
aurora-web:
<<: *comun
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./web/index.html:/usr/share/nginx/html/index.html:ro
- ./web/nginx.conf:/etc/nginx/conf.d/default.conf:ro
stop_signal: SIGQUIT
healthcheck:
<<: *sonda
test: ["CMD", "wget", "--spider", "-q", "http://localhost/"]
deploy:
resources:
limits: { memory: 128M, cpus: "0.5", pids: 50 }
networks: [aurora-net]
volumes:
aurora-datos:
networks:
aurora-net:
driver: bridgeCincuenta líneas de bash imperativo se han convertido en un fichero declarativo, versionable y legible, y de paso ha ganado cosas que el guion no tenía: sondas de salud en los cuatro servicios, rotación de logs y etiquetas coherentes. Valídalo y levántalo:
cd ~/aurora-libros
docker compose config --quiet && docker compose up -d --build
docker compose ps --format "table {{.Service}}\t{{.Status}}"SERVICE STATUS
aurora-api Up 25 seconds (healthy)
aurora-cache Up 35 seconds (healthy)
aurora-db Up 35 seconds (healthy)
aurora-web Up 24 seconds (healthy)Los cuatro servicios healthy. Que hayan arrancado en el orden correcto es suerte, porque todavía no hay ni un depends_on; eso se arregla en la lección 04-04.
Errores Comunes y Consejos
Poner container_name por costumbre. Rompe el escalado y la coexistencia de proyectos, y no aporta nada: para hablar entre servicios se usa el nombre del servicio.
Usar un volumen con nombre sin declararlo arriba. Compose falla con service refers to undefined volume. Los bind mounts no necesitan declaración; los volúmenes con nombre, sí.
Esperar que depends_on a secas espere a que el servicio esté listo. Solo espera a que arranque. Sin condition: service_healthy seguirás teniendo carreras de arranque.
Definir un healthcheck sin start_period. El servicio se marca unhealthy durante su arranque normal y arrastra a todo lo que dependa de él.
Escribir test: curl -f http://localhost/salud en una imagen Alpine. curl no viene instalado en las imágenes Alpine oficiales; wget sí. Un healthcheck que invoca un binario inexistente falla siempre, y el síntoma —unhealthy sin más pistas— despista mucho.
Consejo: empieza cada servicio nuevo con image, restart y healthcheck, y añade el resto solo cuando lo necesites. Un compose.yaml con claves que nadie sabe por qué están es tan malo como un guion de bash.
Ejercicios
Ejercicio 1. Traduce a un servicio de Compose este comando, sin omitir ninguna opción, y explica dónde va cada una:
docker run -d --name aurora-informes --network aurora-net \
-u 1001:1001 -w /app -e TZ=Europe/Madrid --read-only --tmpfs /tmp \
-v aurora-informes-salida:/salida --memory 192m --cpus 0.5 \
--restart on-failure:2 --stop-timeout 20 \
--health-cmd 'wget --spider -q http://localhost:4000/salud' --health-interval 15s \
auroralibros/aurora-informes:0.3.0 node informes.js --diarioEjercicio 2. El bloque x-comun del fichero de Aurora Libros incluye labels. Añade a aurora-db una etiqueta propia com.auroralibros.componente: "base-de-datos" y comprueba con docker compose config qué pasa con la etiqueta heredada. Explica el resultado y propón una solución.
Ejercicio 3. Declara un volumen aurora-copias que apunte a un volumen externo ya existente llamado respaldos-aurora, móntalo de solo lectura en aurora-db en /respaldos, y demuestra que docker compose down -v no lo borra.
Soluciones
Solución 1.
aurora-informes:
image: auroralibros/aurora-informes:0.3.0
command: ["node", "informes.js", "--diario"] # todo lo que va tras la imagen
user: "1001:1001"
working_dir: /app
environment: { TZ: Europe/Madrid }
read_only: true
tmpfs: [/tmp]
volumes:
- aurora-informes-salida:/salida
restart: on-failure:2
stop_grace_period: 20s
healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://localhost:4000/salud"]
interval: 15s
deploy:
resources:
limits: { memory: 192M, cpus: "0.5" }
networks: [aurora-net]--name se omite deliberadamente (el nombre del servicio ya identifica al contenedor), --network pasa a networks, los límites bajan a deploy.resources.limits, --stop-timeout se convierte en stop_grace_period con unidades, y los argumentos posteriores a la imagen se convierten en command en forma de lista.
Solución 2. Añadiendo labels: { com.auroralibros.componente: "base-de-datos" } al servicio aurora-db:
La etiqueta com.auroralibros.proyecto ha desaparecido: <<: fusiona solo al primer nivel, y como el servicio define su propia clave labels, esta sustituye por completo al mapa heredado. La solución es una segunda ancla para el contenido de las etiquetas:
x-etiquetas: &etiquetas
com.auroralibros.proyecto: "aurora-libros"
services:
aurora-db:
<<: *comun
labels:
<<: *etiquetas
com.auroralibros.componente: "base-de-datos"Ahora config muestra las dos. Regla general: cuando fusiones anclas, verifica siempre con docker compose config; lo que crees que hereda y lo que hereda de verdad no siempre coinciden.
Solución 3. Tras docker volume create respaldos-aurora, añade el montaje a aurora-db y la declaración externa:
volumes:
- aurora-copias:/respaldos:ro # dentro de aurora-db
volumes:
aurora-datos:
aurora-copias:
external: true
name: respaldos-auroradocker compose up -d
docker compose exec aurora-db touch /respaldos/prueba # debe fallar: :ro
docker compose down -v
docker volume ls --format "{{.Name}}" | grep -E "respaldos|aurora-datos"down -v ha borrado aurora-libros_aurora-datos, que era del proyecto, pero respaldos-aurora sigue ahí: al ser external, Compose lo considera prestado y no lo gestiona. Es el mecanismo que debes usar para cualquier volumen cuya pérdida sea inaceptable.
Conclusión
Ya tienes la referencia completa de un servicio de Compose, y sobre todo el mapa mental que la sostiene: casi cada clave es una opción de docker run con otro nombre, y solo depends_on expresa algo que la CLI imperativa no sabía decir. Sabes cuándo usar image y cuándo build —y por qué a menudo las dos juntas—, por qué container_name sobra casi siempre, cómo se traducen command, entrypoint, user, init, stop_signal y stop_grace_period, y las dos formas —corta y larga— de ports y volumes, con el matiz de que la larga falla en lugar de crear un directorio vacío cuando el bind no existe.
Dominas el bloque healthcheck completo, incluido el start_period que evita marcar como enfermo a un servicio que solo está arrancando, y conoces la diferencia entre las tres condiciones de depends_on: service_started, service_healthy y service_completed_successfully. Sabes que restart tiene los mismos cuatro valores de siempre y que deploy.resources.limits sí se aplica fuera de Swarm. Declaras volúmenes y redes en los bloques de nivel superior, blindas los datos críticos con external: true, aíslas con internal: true, y evitas la repetición con anclas x-/&/*/<<: sabiendo que la fusión es superficial. Y tienes el compose.yaml con los cuatro servicios de Aurora Libros declarados.
En la lección siguiente, Comandos de Docker Compose, pasarás del fichero a la CLI: el ciclo de vida completo (up y su reconciliación, down y el peligro de -v, start, stop, restart, pause), la observación (ps, logs, top, stats, events), la diferencia esencial entre exec y run, la construcción y publicación, el escalado local con --scale y por qué choca con los puertos fijos, y la selección de ficheros y proyecto con -f, -p y COMPOSE_FILE.
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
