# Docker Compose desde cero para levantar aplicaciones completas

**Categoría:** DevOps y cloud · **Nivel:** Intermedio · **Lectura:** 15 min
**Publicada:** 2026-07-28 · **Actualizada:** 2026-07-28 · **Autoría:** Underc0de
**Versión HTML (canónica):** https://underc0de.org/guias/devops-cloud/docker-compose-para-levantar-aplicaciones-completas/

## Respuesta rápida

**Docker Compose** es una herramienta que permite definir y ejecutar una aplicación de **varios contenedores** como un único conjunto. Una app real casi nunca es un solo contenedor: suele tener, por ejemplo, un servicio *web*, una *base de datos* y una *caché*, que deben arrancar, conectarse entre sí y compartir configuración. Levantar eso a mano —un docker run por servicio, creando redes y volúmenes uno a uno— es tedioso y propenso a errores. Compose lo resuelve describiendo **todo el conjunto en un archivo** llamado compose.yaml: qué servicios hay, de qué imagen sale cada uno, qué puertos exponen, qué variables reciben, qué volúmenes usan y en qué orden dependen. Con un solo comando, docker compose up, se levanta la aplicación entera; con docker compose down, se apaga y limpia. Sus tres claves: la **red** —Compose crea una red propia donde cada servicio se localiza por su *nombre*, así la web se conecta a la base de datos usando db como host, sin IPs—; los **volúmenes** —para que los datos de la base sobrevivan a reiniciar el contenedor—; y **depends_on** —para ordenar el arranque—. Su gran valor es la **reproducibilidad**: el mismo archivo levanta el mismo entorno en tu máquina, en la de un compañero y en el servidor. Es la forma estándar de correr aplicaciones multi-contenedor en desarrollo y en despliegues pequeños; para escalar a muchas máquinas, el salto es a [Kubernetes](../kubernetes-para-principiantes-pods-deployments-y-services/index.md).

## Qué es Docker Compose

Esta guía da por sabido lo básico de [Docker](../docker-desde-cero-imagenes-contenedores-y-volumenes/index.md) (imagen, contenedor, volumen). **Compose** es la capa de encima: en vez de manejar contenedores **uno a uno**, describe la **aplicación completa** como un conjunto de **servicios** que colaboran. Un *servicio* es cada pieza de la app (la web, la base de datos…), y Compose se encarga de crearlas, conectarlas y gestionarlas juntas.

> **El problema que resuelve**
>
> Sin Compose, levantar una app de tres servicios significa recordar y ejecutar tres docker run distintos, con sus flags de puertos, variables, volúmenes y red, y en el orden correcto. Cambiar algo obliga a rehacerlo todo, y explicárselo a otra persona es una lista de instrucciones frágiles. Con Compose, ese conocimiento vive en **un archivo versionado** junto al código: cualquiera clona el repositorio, ejecuta docker compose up y obtiene **exactamente el mismo entorno**. Esa reproducibilidad es su razón de ser.

## El archivo compose.yaml

El archivo es **declarativo**: describe *cómo debe quedar* la aplicación, no los pasos. Se escribe en YAML, y su corazón es la sección services:

```text
# compose.yaml — una app web con base de datos y caché
services:
  web:
    build: .                 # construye la imagen desde el código local
    ports:
      - "8080:80"            # puerto del host : puerto del contenedor
    environment:
      - DB_HOST=db           # se conecta a "db" por su nombre de servicio
    depends_on:
      - db

  db:
    image: postgres:16       # imagen oficial
    environment:
      - POSTGRES_PASSWORD=ejemplo
    volumes:
      - datos_db:/var/lib/postgresql/data   # los datos persisten

  cache:
    image: redis:7           # caché en memoria

volumes:
  datos_db:                  # volumen con nombre, gestionado por Docker
```

> **Los comandos que usarás a diario**
>
> docker compose up -d levanta todo en segundo plano; docker compose down lo apaga y elimina los contenedores y la red (los volúmenes con nombre se conservan salvo que pidas borrarlos). docker compose logs -f sigue los registros de todos los servicios; docker compose ps lista lo que está corriendo; y docker compose up --build reconstruye las imágenes cuando cambió el código. Con esos cinco te movés en el día a día.

## Redes, volúmenes y orden

Tres conceptos separan un compose que funciona de uno que da errores raros. Compose los gestiona por vos, pero conviene entenderlos.

| Concepto | Qué hace Compose | Por qué importa |
|---|---|---|
| Red | Crea una red privada; cada servicio se localiza por su nombre | La web usa db como host, sin IPs ni configuración manual |
| Volúmenes | Monta almacenamiento persistente | Los datos de la base sobreviven a reiniciar o recrear el contenedor |
| depends_on | Ordena el arranque de los servicios | La web no arranca antes que su base de datos |

> **Atención**
>
> El error más común: creer que depends_on garantiza que la base de datos esté *aceptando conexiones* antes de arrancar la web. Solo garantiza el **orden de inicio del contenedor**, no que el servicio de dentro esté operativo —una base de datos tarda unos segundos en estar lista tras arrancar—. Para esperar de verdad, se usa un **healthcheck** (una comprobación de salud) en la base y condition: service_healthy en el depends_on de la web, o bien la aplicación reintenta la conexión al inicio. Ignorar esto produce el clásico «funciona a veces» según qué contenedor gane la carrera.

> **Atención**
>
> Poner contraseñas directamente en compose.yaml y subirlas al repositorio es un fallo de seguridad frecuente. Para desarrollo, las variables sensibles se llevan a un archivo .env *no versionado*; para producción, se usan mecanismos de secretos propios de la plataforma. El tema da para más: verlo en la guía de [administrar secretos en pipelines y aplicaciones](../como-administrar-secretos-en-pipelines-y-aplicaciones/index.md).

## Errores frecuentes

- **Creer que depends_on espera a que el servicio esté listo.** Solo ordena el arranque; usar healthchecks o reintentos.
- **No usar volúmenes para la base de datos.** Los datos se pierden al recrear el contenedor.
- **Poner contraseñas en el compose versionado.** Llevar los secretos a un .env no versionado o a un gestor de secretos.
- **Confundir el puerto del host con el del contenedor.** En "8080:80", el primero es el de tu máquina; el segundo, el interno.
- **Conectarse por localhost entre servicios.** Dentro de la red de Compose, cada servicio se llama por su nombre, no localhost.
- **Olvidar --build tras cambiar el código.** Compose reutiliza la imagen anterior si no se lo pedís.
- **Usar Compose para escalar a muchas máquinas.** Es para una máquina; a esa escala, el salto es a un orquestador como Kubernetes.

## Preguntas frecuentes

**¿Qué es Docker Compose y para qué sirve?**
Docker Compose es una herramienta que permite definir y ejecutar aplicaciones formadas por varios contenedores como un único conjunto coordinado, describiéndolas de forma declarativa en un archivo de configuración. La necesidad que cubre surge de que las aplicaciones reales rara vez consisten en un solo contenedor, sino que suelen estar compuestas por varios servicios que colaboran, como por ejemplo un servicio web que atiende las peticiones, una base de datos que almacena la información y una caché que acelera el acceso a datos frecuentes, y todos ellos deben arrancar, comunicarse entre sí y compartir cierta configuración. Levantar y coordinar todos esos contenedores manualmente, ejecutando un comando de ejecución por cada uno con sus opciones de puertos, variables de entorno, volúmenes y redes, y en el orden adecuado, resulta tedioso, difícil de recordar y muy propenso a errores. Docker Compose resuelve este problema permitiendo describir toda la aplicación en un archivo, habitualmente llamado compose punto yaml, en el que se especifica qué servicios la componen, de qué imagen parte cada uno o cómo se construye, qué puertos expone, qué variables de entorno recibe, qué volúmenes utiliza y qué dependencias tiene respecto a otros servicios. Una vez descrita, la aplicación completa se levanta con un único comando de subida y se detiene y limpia con un único comando de bajada, lo que simplifica enormemente el trabajo. Además de la comodidad, su mayor valor es la reproducibilidad, ya que el mismo archivo, al estar versionado junto al código, permite que cualquier persona del equipo levante exactamente el mismo entorno en su máquina, y que ese entorno coincida con el de un servidor, evitando el clásico problema de que algo funciona en un sitio y no en otro. Docker Compose es la forma estándar de trabajar con aplicaciones de varios contenedores en entornos de desarrollo y en despliegues de tamaño pequeño en una sola máquina, mientras que para escalar una aplicación a lo largo de muchas máquinas la herramienta adecuada pasa a ser un orquestador como Kubernetes.

**¿En qué se diferencia Docker Compose de Docker?**
Docker y Docker Compose están estrechamente relacionados pero operan a niveles distintos, y entender esa diferencia ayuda a usarlos correctamente. Docker es la tecnología base que permite empaquetar aplicaciones en imágenes y ejecutarlas como contenedores, y su herramienta de línea de comandos trabaja fundamentalmente a nivel de contenedor individual: con ella se construye una imagen, se ejecuta un contenedor a partir de ella, se le asignan puertos, variables de entorno y volúmenes, y se gestiona su ciclo de vida, pero cada contenedor se maneja de forma independiente mediante comandos separados. Docker Compose es una capa que se apoya sobre Docker y que sube el nivel de abstracción del contenedor individual al de la aplicación completa formada por varios contenedores. En lugar de lanzar y coordinar manualmente cada contenedor con sus opciones, Compose permite describir en un único archivo el conjunto de servicios que componen la aplicación, junto con sus imágenes, puertos, variables, volúmenes, redes y dependencias, y luego gestionar todo ese conjunto con comandos únicos que actúan sobre la aplicación entera, como levantarla o detenerla de una sola vez. Dicho de otro modo, Docker se ocupa de los contenedores como piezas sueltas, mientras que Compose se ocupa de orquestar esas piezas para que funcionen juntas como una aplicación coherente en una máquina. Compose no sustituye a Docker ni añade una tecnología de contenedores distinta, sino que utiliza el mismo motor por debajo; lo que aporta es comodidad, orden y reproducibilidad al trabajar con aplicaciones de múltiples servicios, evitando la repetición de comandos y centralizando la configuración en un archivo versionable. Conviene además no confundir Docker Compose con los orquestadores de contenedores a gran escala como Kubernetes: Compose está pensado para coordinar contenedores dentro de una sola máquina, ideal para desarrollo y despliegues pequeños, mientras que los orquestadores gestionan contenedores distribuidos en clústeres de muchas máquinas, con capacidades de escalado, recuperación y balanceo que Compose no ofrece.

**¿Cómo se comunican los servicios entre sí en Compose?**
Los servicios definidos en un archivo de Docker Compose se comunican entre sí a través de una red privada que Compose crea automáticamente para la aplicación, y el mecanismo clave que hace que esa comunicación sea sencilla es la resolución de nombres por servicio. Cuando se levanta una aplicación con Compose, todos sus servicios se conectan por defecto a una misma red interna y aislada, y dentro de esa red cada servicio es localizable simplemente por el nombre que se le ha dado en el archivo de configuración. Esto significa que si, por ejemplo, se tiene un servicio llamado base de datos y un servicio web, el servicio web puede conectarse a la base de datos usando ese nombre como si fuera la dirección del servidor, sin necesidad de conocer ni configurar direcciones numéricas, que además podrían cambiar. Compose se encarga por debajo de traducir ese nombre a la dirección interna correspondiente, de modo que la configuración de la aplicación puede referirse a los otros servicios de forma estable y legible. Un punto importante que suele causar confusión es que, dentro de la red de Compose, un servicio no debe intentar comunicarse con otro usando la dirección de bucle local, que hace referencia al propio contenedor y no al servicio vecino; la comunicación entre servicios se hace siempre por el nombre del servicio de destino. En cuanto a los puertos, conviene distinguir entre la comunicación interna entre servicios, que ocurre dentro de la red privada usando los puertos internos de cada contenedor, y la exposición hacia el exterior, que se configura mapeando un puerto de la máquina anfitriona a un puerto del contenedor para poder acceder al servicio desde fuera, por ejemplo desde el navegador. Gracias a este modelo de red con nombres, describir cómo se conectan los servicios de una aplicación en Compose resulta muy natural, y basta con referirse a cada servicio por su nombre para que todo el conjunto funcione de forma coordinada.

**¿Por qué mi base de datos pierde los datos al reiniciar?**
Si una base de datos gestionada con Docker Compose pierde sus datos al reiniciar o recrear su contenedor, la causa casi siempre es que no se ha configurado un volumen para almacenar de forma persistente esos datos, y conviene entender por qué ocurre. Los contenedores están diseñados para ser efímeros, lo que significa que cualquier dato escrito dentro del sistema de archivos propio de un contenedor desaparece cuando ese contenedor se elimina y se vuelve a crear, algo que sucede con operaciones habituales como bajar y volver a levantar la aplicación o reconstruir las imágenes. Por tanto, si la base de datos guarda su información únicamente dentro del contenedor, esa información se perderá en cuanto el contenedor se recree. La solución es utilizar un volumen, que es un mecanismo de almacenamiento gestionado por Docker que vive fuera del ciclo de vida del contenedor y que persiste aunque el contenedor se elimine y se cree de nuevo. En el archivo de Compose, esto se logra declarando un volumen y montándolo en la ruta interna donde la base de datos guarda sus ficheros de datos, de manera que todo lo que la base escriba en esa ruta quede realmente en el volumen persistente y no en el contenedor efímero. Con esa configuración, al reiniciar, bajar y subir o incluso recrear el contenedor de la base de datos, los datos siguen intactos porque residen en el volumen. Es importante saber además que el comando que baja la aplicación elimina por defecto los contenedores y la red, pero conserva los volúmenes con nombre, de modo que los datos sobreviven a esa operación; solo se borrarían los volúmenes si se solicita explícitamente al bajar la aplicación con la opción correspondiente. Por ello, la recomendación es configurar siempre un volumen para cualquier servicio que deba conservar información, como bases de datos o almacenes de archivos, y tener claro qué operaciones conservan y cuáles eliminan esos volúmenes, para evitar tanto pérdidas accidentales de datos como la acumulación de volúmenes que ya no se usan.

**¿Docker Compose sirve para producción?**
Docker Compose puede utilizarse en producción, pero con matices importantes que conviene tener claros para no elegir la herramienta equivocada según la escala y las necesidades del proyecto. Compose está diseñado para coordinar contenedores dentro de una única máquina, por lo que resulta perfectamente válido y muy práctico para despliegues de producción de tamaño pequeño o moderado que se ejecutan en un solo servidor, como aplicaciones internas, proyectos personales, servicios de bajo tráfico o entornos donde la simplicidad y la facilidad de gestión son prioritarias frente a la alta disponibilidad o el escalado masivo. En esos casos, un archivo de Compose bien hecho, con volúmenes para los datos persistentes, gestión adecuada de los secretos mediante variables de entorno externas o mecanismos de secretos en lugar de contraseñas en texto plano, comprobaciones de salud para los servicios y políticas de reinicio, puede sostener una aplicación en producción de forma razonable. Sin embargo, Compose tiene limitaciones intrínsecas que lo hacen inadecuado para escenarios más exigentes. Al operar sobre una sola máquina, no ofrece por sí mismo capacidades como distribuir los contenedores entre varios servidores, escalar automáticamente en función de la carga, recuperar servicios trasladándolos a otra máquina si una falla, o realizar balanceo de carga y despliegues sin interrupción de forma nativa a gran escala. Cuando una aplicación necesita alta disponibilidad, tolerancia a fallos de hardware, escalado horizontal significativo o gestión de muchos servicios a lo largo de un clúster de máquinas, la herramienta adecuada deja de ser Compose y pasa a ser un orquestador de contenedores como Kubernetes, que está pensado precisamente para esos requisitos. Por tanto, la respuesta equilibrada es que Compose sí sirve para producción en entornos de una sola máquina y de escala contenida, donde aporta simplicidad y reproducibilidad, pero no es la opción correcta para sistemas grandes, distribuidos o con altos requisitos de disponibilidad y escalado, para los que conviene dar el salto a un orquestador.

**¿Qué comandos de Docker Compose necesito conocer?**
Para trabajar con Docker Compose en el día a día basta con manejar un pequeño conjunto de comandos esenciales que cubren el ciclo de vida completo de una aplicación de varios contenedores. El comando fundamental es el de subida, que lee el archivo de configuración y levanta todos los servicios de la aplicación, creando las redes y los volúmenes necesarios y conectando los contenedores entre sí; suele ejecutarse en modo separado o de segundo plano para que la terminal quede libre, y admite una opción para reconstruir las imágenes cuando ha cambiado el código de la aplicación, algo importante porque de lo contrario Compose reutiliza las imágenes ya construidas. El comando complementario es el de bajada, que detiene y elimina los contenedores y la red asociados a la aplicación, dejando el entorno limpio, aunque conservando por defecto los volúmenes con nombre para no perder los datos persistentes, aspecto clave que conviene recordar. Para observar qué está ocurriendo dentro de la aplicación es muy útil el comando de registros, que muestra la salida de los servicios y que, en modo de seguimiento, permite ver los mensajes en tiempo real, lo que resulta imprescindible para diagnosticar problemas. Otro comando habitual es el que lista el estado de los servicios de la aplicación, permitiendo ver rápidamente qué contenedores están en marcha, cuáles se han detenido y en qué puertos están escuchando. También son frecuentes los comandos para detener y arrancar servicios sin eliminarlos, para ejecutar un comando dentro de un servicio en marcha, por ejemplo para abrir una consola de la base de datos o inspeccionar algo, y para reconstruir imágenes concretas. Con el dominio de la subida, la bajada, los registros, el listado de estado y la reconstrucción de imágenes se cubre la inmensa mayoría del trabajo cotidiano, y a partir de ahí se pueden ir incorporando comandos y opciones más específicas según las necesidades. La documentación oficial recoge la referencia completa de todos ellos para cuando se necesite algo puntual.

## Fuentes

Documentación oficial y material de la comunidad consultados para esta guía. Fecha de consulta: 28 de julio de 2026.

### Aportes de la comunidad Underc0de

1. **Underc0de, foro.** [Sección GNU/Linux](https://underc0de.org/foro/gnu-linux/). Contenedores y despliegue.
2. **Underc0de, foro.** [Sección Desarrollo web](https://underc0de.org/foro/desarrollo-web/). Entornos de desarrollo.

### Documentación oficial

1. **Docker.** [Docker Compose overview](https://docs.docker.com/compose/). Documentación oficial de Compose.
2. **Docker.** [Compose file reference](https://docs.docker.com/reference/compose-file/). Referencia del archivo compose.
3. **Docker.** [Networking in Compose](https://docs.docker.com/compose/how-tos/networking/). Cómo se comunican los servicios.
4. **Docker.** [docker compose CLI](https://docs.docker.com/reference/cli/docker/compose/). Referencia de los comandos.

## Guías relacionadas

- [Docker desde cero](../docker-desde-cero-imagenes-contenedores-y-volumenes/index.md)
- [Kubernetes para principiantes](../kubernetes-para-principiantes-pods-deployments-y-services/index.md)
- [Administrar secretos](../como-administrar-secretos-en-pipelines-y-aplicaciones/index.md)
- [Pipelines CI/CD](../como-crear-pipelines-ci-cd-con-github-actions/index.md)
- [Índice de DevOps y cloud](../index.md)
