Herramientas

Docker Compose: el día a día. Cómo ver qué funciona y qué no

Si acabas de montar tu aplicación en Docker Compose, la primera pregunta que haces cada mañana es siempre la misma: ¿está todo levantado y funcionando? Y la segunda, cuando algo va mal: ¿dónde está el problema?

Este manual te enseña exactamente cómo comprobar eso: los comandos que necesitas en el día a día para saber qué está corriendo, qué falla, cómo entrar dentro de un contenedor y cómo actualizar tu aplicación sin quebrar nada.

El panorama: Docker vs Compose

Antes de empezar, una aclaración mental importante porque es la mayor fuente de confusión:

  • Docker es la herramienta global. Todos los contenedores en tu máquina, sin importar para qué proyecto.
  • Compose es el orquestador local de tu proyecto. Solo se ocupa de los servicios que definiste en tu docker-compose.yml de esa carpeta.

Piénsalo así:

  • docker ps → “¿Qué contenedores hay en TODA mi máquina?” (proyecto A, proyecto B, BD compartida…)
  • docker compose ps → “¿Qué servicios del mi proyecto actual están en marcha?”

Para la mayoría de tu día a día usarás Compose. Los comandos de Docker puro son para cuando necesitas ver el panorama completo o limpiar la máquina.

Nota técnica: Si tu archivo se llama algo distinto a docker-compose.yml, necesitarás añadir -f nombre.yml a los comandos de Compose. Y donde veas app, sustituye por el nombre real de tu servicio en el compose.

Lo primero: ¿qué está en marcha?

La pregunta más frecuente: ahora mismo, ¿qué corre?

docker compose ps

Esto te muestra solo los servicios de TU proyecto. Salida típica:

NAME      COMMAND             STATUS              PORTS
app       python main.py      Up 3 minutes        0.0.0.0:8000->8000/tcp
db        postgres            Up 5 minutes (healthy)
redis     redis-server        Up 3 minutes

Qué mirar en cada columna:

  • STATUS → aquí está toda la información:
  • Up 3 minutes = corriendo normal.
  • Up 3 minutes (healthy) = corriendo y pasa los chequeos de salud (healthcheck). Es lo ideal.
  • Up 3 minutes (unhealthy) = el contenedor sigue vivo, pero la aplicación no responde bien. Algo falla dentro.
  • Restarting = se cae y se reinicia una y otra vez en bucle. Hay un error en el código o la configuración.
  • Exited (0) = terminó correctamente y se paró. Exited (1) u otro número = terminó con error.
  • PORTS → qué puertos expone y dónde están mapeados. 8000->8000 significa que el puerto 8000 del contenedor está accesible en el 8000 de tu máquina.
  • NAMES → el nombre del servicio, que usarás en otros comandos.

Ver TODO lo que corre en la máquina

Si quieres ver todos los contenedores (no solo los de tu proyecto):

docker ps

E incluso los parados:

docker ps -a

Los logs: dónde está la verdad

Cuando algo no funciona, el primer sitio donde mirar son siempre los logs. Son tu conexión directa a lo que está pasando dentro del contenedor.

Leer los últimos logs

docker compose logs app --tail 50

Te muestra las últimas 50 líneas. --tail 10, --tail 100, lo que necesites.

Seguir los logs en vivo

docker compose logs app -f

El -f significa “follow” (seguir). Verás el log en tiempo real. Ctrl+C para salir. Muy útil mientras estás desarrollando o debugueando.

Todos los servicios juntos

docker compose logs -f

Sin especificar app, ves los logs de todos los servicios simultáneamente. Útil para ver cómo interactúan.

Con marca de tiempo

docker compose logs app -f --timestamps

Si hay un problema a las 14:32:17, verlo en el log es mucho más fácil que en medio de un flujo de eventos.

Solo lo reciente

docker compose logs app --since 1h

Solo logs de la última hora. Útil cuando tienes meses de historial y buscas algo específico.

El truco del “cola + follow”

Para no ahogarte en logs antiguos pero sí ver lo nuevo en vivo:

docker compose logs app --tail 20 -f

Empieza mostrando las últimas 20 líneas, luego sigue en tiempo real. Lo mejor de los dos mundos.

Arrancar, parar, reiniciar: el ciclo de vida

El ciclo que haces constantemente.

Arrancar todo

docker compose up -d

El -d significa “detached” (desapegado): se ejecuta en segundo plano. Sin -d, ocuparías la terminal viendo los logs.

Si es la primera vez, Compose descargará las imágenes necesarias. Puede tardar.

Parar sin borrar

docker compose stop

Los contenedores se detienen, pero siguen existiendo. Puedes volver a arrancarlos con:

docker compose start

Es como pausar: todo se conserva en memoria, tus volúmenes de datos están intactos.

Reiniciar

docker compose restart app

O todos:

docker compose restart

Equivale a parar y volver a arrancar. A veces lo necesitas cuando algo se queda “pegado”.

Desmontar completamente

docker compose down

Para Y ELIMINA los contenedores y la red de tu proyecto. PERO los volúmenes (datos persistentes) se conservan. Bases de datos, modelos descargados, todo sigue ahí.

Si de verdad quieres empezar de cero y BORRAR TODO, incluidos datos:

docker compose down -v

El -v de “volúmenes”. Cuidado: pierdes modelos descargados, bases de datos y cualquier dato guardado en volúmenes.

Regla mental

  • stop → pausa (contenedores existen, pueden reanudarse).
  • down → desmonta (contenedores se borran, datos persisten).
  • down -v → arrasa (borra TODO, incluyendo datos).

Entrar dentro del contenedor

A veces necesitas inspeccionar qué hay dentro: variables de entorno, archivos, ejecutar comandos puntuales.

Abrir una shell interactiva

docker compose exec app sh

Te da una terminal dentro del contenedor. Ahora escribes como si estuvieras dentro:

# Ver variables de entorno
printenv

# Listar archivos
ls -la /app

# Ver un archivo
cat config.json

# Salir
exit

Si la imagen lo tiene, puedes pedir bash en lugar de sh:

docker compose exec app bash

(Las imágenes pequeñas, como Alpine, solo tienen sh.)

Ejecutar un comando concreto sin abrir shell

docker compose exec app printenv DATABASE_URL

Te muestra solo el resultado del comando, sin abrir sesión interactiva.

Ejecutar un comando en un contenedor nuevo (efímero)

docker compose run --rm app python -c "print('hola')"

Esto crea un contenedor nuevo, ejecuta el comando, y lo borra (--rm) cuando acaba. Útil para tareas suelta que no necesitan modificar estado.

Diferencia importante:

  • exec → entra en un contenedor ya en marcha.
  • run → crea un contenedor nuevo para esa tarea.

Diagnóstico e inspección profunda

Cuando algo está raro pero no es obvio.

Ver recursos en vivo

docker stats

CPU, memoria, red que consume cada contenedor. Ctrl+C para salir. Si algo come memoria como loco, aquí lo verás al instante.

Inspección detallada de un contenedor

docker inspect nombre_o_id_contenedor

Te da un JSON gigante con TODO: IP, puertos, volúmenes montados, variables de entorno, estado de salud, última hora de inicio, etc.

Si solo quieres el estado de salud:

docker inspect --format '{{json .State.Health}}' nombre | python3 -m json.tool

Útil cuando ves unhealthy en docker ps y quieres saber exactamente por qué.

Procesos corriendo dentro

docker compose top app

Te muestra qué procesos están corriendo dentro del contenedor. Tipo ps pero dentro del contenedor.

Imágenes, volúmenes, redes: la infraestructura

Ver imágenes descargadas

docker images

Todas las imágenes que tienes en la máquina (descargadas o construidas). Ocupan espacio.

Ver volúmenes (donde van los datos)

docker volume ls

Los volúmenes son donde persisten datos: modelos descargados, bases de datos, archivos que carga tu app.

Ver redes

docker network ls

Compose crea una red por proyecto. Los contenedores dentro de una red pueden comunicarse por nombre de servicio.

Cuánto espacio ocupa todo

docker system df

Resumen de cuánto espacio tienen imágenes, contenedores y volúmenes. Útil para saber si necesitas limpiar.

Limpieza: liberar espacio

Docker acumula basura: imágenes viejas, contenedores parados, caché de builds. De vez en cuando conviene limpiar.

Limpieza básica

docker system prune

Borra:

  • Contenedores parados.
  • Redes que no usa nadie.
  • Imágenes “colgadas” (sin etiqueta, sin usar).
  • Caché de build.

Es seguro: no toca volúmenes ni imágenes que usan contenedores vivos.

Limpieza agresiva

docker system prune -a

Igual que arriba, pero además borra todas las imágenes no usadas por ningún contenedor. Si luego necesitas esa imagen, la descargará de nuevo.

Borrar solo volúmenes

docker volume prune

Borra volúmenes que no usa nadie. Cuidado: puede eliminar datos persistentes (modelos descargados, base de datos antiguas). Revisa con docker volume ls antes.

Actualizar la aplicación

El ciclo habitual cuando cambias el código o la configuración.

Reconstruir todo con cambios

docker compose up -d --build

Reconstruye la imagen (importante si cambiaste requirements.txt, Dockerfile, etc.) y arranca. El -d en segundo plano.

Solo cambió la configuración (variables de entorno, .env)

docker compose up -d --force-recreate

No reconstruye la imagen (más rápido), pero sí destruye y crea contenedores nuevos para que piquen las nuevas variables. Necesario si tocaste .env sin cambiar código.

Reconstrucción totalmente limpia

docker compose build --no-cache && docker compose up -d

Ignora la caché de capas Docker (que normalmente reutiliza pasos anteriores). Usa esto si tienes dudas de que la caché esté causando problemas.

Flujos típicos: recetas de troubleshooting

Pregunta: “¿Está todo bien ahora mismo?”

docker compose ps

Mira STATUS. Si todo dice Up y healthy, estás bien.

Pregunta: “La app no responde, ¿qué pasa?”

# 1. ¿El contenedor está sano?
docker compose ps

# 2. ¿Qué dice el log?
docker compose logs app --tail 80

# 3. ¿La configuración es la esperada?
docker compose exec app printenv DATABASE_URL

Sigue ese orden. El 80% de los problemas está en uno de esos tres sitios.

Pregunta: “Cambié configuración y quiero aplicarla”

docker compose up -d --force-recreate

Recrea los contenedores para que lean el .env actualizado.

Pregunta: “Desplegué una versión nueva del código”

docker compose up -d --build
docker compose ps
docker compose logs app --tail 50 -f

Reconstruye con el código nuevo, verifica que levantó bien, y sigue los logs un momento para asegurarte de que no explota.

Pregunta: “Quiero empezar de cero (borrando datos)”

docker compose down -v
docker compose up -d --build

Borra todo incluidos volúmenes (-v), luego reconstruye todo limpio.

Chuleta rápida

Imprime esto, tenlo en una esquina:

Quiero…Comando
Ver mi proyecto (servicios activos)docker compose ps
Ver TODO en la máquinadocker ps
Ver logs últimas líneasdocker compose logs app --tail 50
Seguir logs en vivodocker compose logs app -f
Arrancar en segundo planodocker compose up -d
Parar (sin borrar)docker compose stop
Reanudar lo paradodocker compose start
Reiniciar un serviciodocker compose restart app
Recrear tras cambio de configdocker compose up -d --force-recreate
Actualizar con código nuevodocker compose up -d --build
Entrar al contenedordocker compose exec app sh
Ver recursos (CPU/RAM)docker stats
Desmontar proyectodocker compose down
Desmontar + borrar datosdocker compose down -v
Liberar espaciodocker system prune

Conclusiones

Docker Compose simplifica mucho la gestión del día a día, pero solo si sabes dónde mirar y qué preguntarle. Los 5 comandos que usarás el 80% del tiempo son:

  1. docker compose ps — ¿está todo bien?
  2. docker compose logs app -f — ¿qué está pasando?
  3. docker compose up -d --build — actualizar código.
  4. docker compose up -d --force-recreate — actualizar configuración.
  5. docker compose exec app sh — entrar a inspeccionar.

Memoriza esos, y el resto es googleable. La máquina está bajo control.

Nota: La imagen de este artículo fue generada utilizando un modelo de inteligencia artificial.

¿Te ha parecido de utilidad el contenido?

Daniel Rodríguez

Share
Published by
Daniel Rodríguez
Tags: Docker

Recent Posts

Migrar tslane a un paquete dual CommonJS y ESM con tsup y Vitest

tslane es la plantilla que uso como punto de partida para mis librerías TypeScript, nacida…

5 días ago

Cómo construir tu primer scorecard paso a paso

En los artículos anteriores de esta serie vimos la teoría detrás del credit scoring: qué…

1 semana ago

Actualizar expresslanets a ES Modules con tsx y Vitest

expresslanets es la plantilla de API REST con Express y TypeScript que empezó como una…

2 semanas ago

Pareto/NBD: cuando el abandono silencioso cambia el CLV

En el artículo del Dashboard vimos que Pareto/NBD aparecía junto a BG/NBD con un ajuste…

2 semanas ago

Por qué migrar tus proyectos TypeScript a ES Modules en 2026

Durante años, CommonJS (require/module.exports) ha sido la forma por defecto de organizar módulos en Node.js,…

3 semanas ago

Método del codo: interpretación correcta y limitaciones

Cuando usas k-means tienes que decidir algo incómodo de entrada: cuántos grupos, , vas a…

3 semanas ago

This website uses cookies.