3.1 · El archivo compose.yml : servicios, puertos, volúmenes

Nivel 3 · Docker Compose

3.1El archivo compose.yml : servicios, puertos, volúmenes

Objetivo: describir una aplicación completa (web + base) en un compose.yml legible.
Tiempo estimado: 14 min · lectura autónoma · Si solo tienes 5 min: lee «Lo esencial en 30s» + el esquema.

Lo esencial en 30 segundos

  • Declarar el estado deseado, no las órdenes : cada servicio tiene su imagen (o build), sus puertos, sus variables, sus volúmenes y su red — Compose lo crea todo desde este archivo versionado.
  • Un servicio = imagen + puertos + env + volúmenes : puertos entre comillas ("8080:80"), volúmenes y redes declarados abajo y creados automáticamente, depends_on para el orden de arranque.
  • YAML : la indentación es la ley : espacios, nunca tabulaciones, dos espacios por nivel — docker compose config valida y muestra el archivo resuelto antes de cualquier lanzamiento.

Mini-caso hilado — Idir sustituye sus líneas de 200 caracteres

Idir, devops junior en Argel, lanza la maqueta de su equipo con dos líneas docker run de 200 caracteres recopiadas de una chuleta — un puerto olvidado, y la demo falla. Escribe un compose.yml de 25 líneas (web + base, volumen nombrado, depends_on), lo valida con docker compose config, lo commitea : desde ahora, un solo archivo da fe y todo el equipo arranca la misma aplicación. Se acabó la doc « cómo lanzar » recitada de memoria.

Este mismo caso vuelve en el curso, el esquema, el guion y el reto 48h.

1. Declarar en lugar de ordenar : el archivo que da fe

Compose sustituye sus docker run por un archivo versionado : en él se describe el ESTADO DESEADO de la aplicación (qué servicios, qué puertos, qué volúmenes, qué redes) y Compose lo crea todo — redes, volúmenes, contenedores en orden. Se acabaron las líneas de 200 caracteres recopiadas de memoria : el compose.yml se commitea, se revisa como código, y constituye el lanzador oficial de la app. Es el paso del gesto manual a lo declarativo.

Cada servicio (web, bdd, caché…) declara su imagen (o su build local), sus puertos ("8080:80", comillas obligatorias en YAML), su environment, sus volúmenes (pgdata:/var/lib/postgresql/data) y su red. depends_on fija el orden de arranque entre servicios. Los volúmenes y redes se declaran abajo del archivo : Compose los crea automáticamente en el primer up.

2. YAML : la indentación es la ley, config es el juez

Compose habla YAML : espacios y nunca tabulaciones, dos espacios por nivel, « : » seguido de un espacio. Casi todos los errores de Compose vienen de ahí : una indentación rota, puertos sin comillas (¡8080:80 leído como un número sexagesimal!), un « : » sin espacio. Escribir despacio, indentar limpio : eso es el 80 % del trabajo.

El reflejo antes de cada lanzamiento : docker compose config. Este comando valida el archivo y muestra el compose RESUELTO — o el error exacto con su línea. Idir ya nunca lanza un up sobre un archivo no validado : config primero, up después. Un archivo por app, commiteado, validado : reproducible en todas partes.

Error frecuente de interpretación: « depends_on espera a que la base esté lista, y los puertos pueden escribirse sin comillas ». No, dos veces. depends_on ORDENA el arranque sin esperar la disponibilidad — la robustez viene de los healthchecks y los reintentos (nivel 4). Y 8080:80 sin comillas se lee como un número sexagesimal en YAML : los puertos siempre se entrecomillan. Ordenar no es esperar, y entrecomillar no es decorativo.
Describir la app en lugar de ordenar Servicios, volúmenes, redes, validación ServiciosImagen + puertos entrecomillados + env + volúmenes + depends_on+Volúmenes + redesDeclarados abajo, creados automáticamente+docker compose configValida y muestra lo resuelto antes del up Un archivo versionado lo describe todo : reproducible en todas partes.
Servicios, volúmenes, redes, validación
Versión en texto del esquema (SEO / lectores de pantalla / traducción): 1) Servicios : Idir declara web (imagen, puertos entrecomillados) y bdd (imagen, contraseña en variable, volumen) en lugar de dos líneas run. 2) Base : volúmenes y redes declarados abajo, creados automáticamente en el primer up. 3) Validación : docker compose config muestra el archivo resuelto o el error exacto antes de todo lanzamiento. Lección : se declara el estado deseado, Compose ejecuta — el archivo commiteado sustituye a la doc.

🔎 Ejemplo concreto — Web + base en 25 líneas, validado antes del lanzamiento

Idir escribe su primer stack web + base, contraseña en variable.

services:
  web:
    image: nginx:1.27
    ports: ["8080:80"]
    depends_on: [bdd]
    networks: [front]
  bdd:
    image: postgres:16.4
    environment:
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes: [pgdata:/var/lib/postgresql/data]
    networks: [front]
volumes:
  pgdata:
networks:
  front:
# Luego : docker compose config (validar), contraseña en .env no commiteado.

Lectura : dos servicios, un volumen persistente, una red, un orden de arranque.

Lección : este archivo commiteado sustituye a toda la doc « cómo lanzar ».

Vocabulario de la sección

Servicio
Un contenedor descrito en Compose (web, bdd, caché) : imagen o build, puertos, variables, volúmenes, red.

Ejemplo sencillo: El servicio web de Idir (nginx, puerto 8080 publicado).

Lo que no es: una línea docker run recopiada de memoria.

Reflejo: un rol aplicativo = un servicio declarado.

depends_on
El orden de arranque entre servicios : lanza la base antes que la web, sin esperar a que esté lista.

Ejemplo sencillo: web depends_on bdd : la base arranca primero.

Lo que no es: una garantía de que la base está disponible.

Reflejo: ordenar con depends_on, fiabilizar con healthcheck + retry.

Volumen Compose
Volumen nombrado declarado abajo del archivo y creado automáticamente : la persistencia de los datos.

Ejemplo sencillo: pgdata montado en /var/lib/postgresql/data.

Lo que no es: datos prisioneros de un contenedor efímero.

Reflejo: todo dato por guardar = volumen nombrado.

config
Comando que valida el compose y muestra el archivo resuelto — o el error exacto.

Ejemplo sencillo: Idir pasa config antes de cada up.

Lo que no es: un up a ciegas sobre un YAML roto.

Reflejo: config primero, up después, siempre.

YAML
El formato indentado del compose.yml : espacios (nunca tabulaciones), « : » + espacio, puertos entre comillas.

Ejemplo sencillo: "8080:80" entrecomillado, dos espacios por nivel.

Lo que no es: tabulaciones y puertos sin entrecomillar.

Reflejo: espacios, dos por nivel, comillas en los puertos.

En la práctica — Escribir su primer stack

  1. Cree una carpeta con el compose.yml web + bdd de arriba (contraseña en ${POSTGRES_PASSWORD}, .env local no commiteado).
  2. Valídelo con docker compose config : lea el archivo resuelto mostrado.
  3. Corrija hasta cero errores (indentación, comillas de los puertos, « : » + espacio).
  4. Commitee el archivo : desde ahora es su lanzador oficial, revisado como código.
Su aplicación se describe en un archivo versionado y validado : reproducible por todo el equipo.

Guion listo para decir — presentar el compose al equipo (30 s)

« Se acabaron las líneas run de 200 caracteres : un solo compose.yml describe web + base — puertos, volumen, orden de arranque — validado por config y commiteado. Cada uno arranca exactamente la misma aplicación, sin chuleta. »

Para decir en reunión de equipo ; proyectar el config resuelto.

Modelo copiar-pegar — stack web + base válido

services:
  web:
    image: nginx:1.27
    ports:
      - "8080:80"
    depends_on:
      - bdd
    networks:
      - front
  bdd:
    image: postgres:16.4
    environment:
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - pgdata:/var/lib/postgresql/data
    networks:
      - front

volumes:
  pgdata:

networks:
  front:
# .env local (NO commiteado) : POSTGRES_PASSWORD=

Independiente

Un compose.yml validado por config y su demo arranca igual en todas partes.

PYME en Argel

Idir commitea el stack web + base : el equipo arranca la misma maqueta sin chuleta.

Equipo de proyecto

Imponer config en verde + commit del compose antes de toda demo compartida.

Principiante

Esta semana : un stack web + base validado con el botón config, luego commiteado.

Prudencia: Contraseña de la base vía el .env local, nunca en duro en el compose commiteado : ${POSTGRES_PASSWORD} en el archivo, valor real solo en el .env (no versionado, proporcionado vía un .env.example).

✓ Buenas prácticas

  • Ponga los puertos entre comillas en YAML ("8080:80"), sistemáticamente.
  • Pase docker compose config antes de cada up, y lea lo resuelto.
  • Un archivo por app, commiteado y revisado como código.

✗ Errores frecuentes

  • Tabulaciones en el YAML : solo espacios, dos por nivel.
  • Puertos sin comillas (8080:80 se convierte en un número sexagesimal).
  • Creer que depends_on espera a que la base esté lista (solo ordena).

Puntos clave

  • Compose DESCRIBE el estado deseado, Docker ejecuta : el archivo versionado sustituye a las líneas run.
  • SERVICIO = imagen (o build) + puertos entrecomillados + env + volúmenes + depends_on para el orden.
  • YAML : espacios, nunca tabulaciones, « : » + espacio — el 80 % de los errores viene de ahí.
  • VOLÚMENES y REDES declarados abajo, creados automáticamente ; config valida antes del up.

Reto 48h — aplique mañana

Sustituya 1 lanzamiento manual por un compose.yml validado (config) y commiteado, con la contraseña en variable.

Lista de salida de la sección
  • Mi app se describe en un archivo versionado.
  • Mis puertos están entrecomillados y mi YAML sin tabulaciones.
  • Mi config está en verde antes de cada up.
Autoevaluación 1-5 : ¿otra persona arranca mi app sin hacerme preguntas ?¿cada contraseña está fuera del archivo commiteado ?

Preguntas frecuentes

¿depends_on espera a que la base esté lista ?

NO : depends_on ORDENA el arranque (la base arranca antes que la web) sin esperar su disponibilidad. Si la web se conecta demasiado pronto, falla : la robustez viene de los healthchecks y los reintentos aplicativos (nivel 4.2). Retenga : ordenar ≠ esperar. Para una maqueta simple, relanzar la web basta ; para un stack real, bucle de reconexión al arrancar en la aplicación.

¿Hay que versionar el compose.yml, y dónde poner los secretos ?

SÍ, siempre : el compose.yml es el lanzador oficial de la app, revisado como código y commiteado. Los SECRETOS nunca figuran en duro : use variables (${POSTGRES_PASSWORD}) alimentadas por un .env local no commiteado (o un secreto gestionado en producción), y versione un .env.example con valores ficticios para documentar las claves esperadas.

Comprueba tu comprensión

¿Qué valida « docker compose config » antes de todo lanzamiento ?

Recursos adicionales (opcional, para ir más allá)

Examen del nivel 3Preguntas inéditas y más difíciles para validar tus conocimientos