Guía práctica de Claude Code y Docker Compose: App local, Postgres, Redis y Worker
Guía práctica para crear con Claude Code un entorno Docker Compose con app, Postgres, Redis y worker.
Docker Compose funciona como el plano de un entorno local: levanta la aplicación, PostgreSQL, Redis y un worker en una sola composición. La documentación oficial de Docker Compose lo presenta como una herramienta para definir y ejecutar aplicaciones con varios contenedores, gestionando servicios, redes y volúmenes desde un archivo YAML.
Esto encaja muy bien con Claude Code. En vez de pedir “hazme un entorno Docker”, conviene darle archivos concretos para revisar: compose.yaml, Dockerfile, .env.example y Makefile. El resultado es más fácil de auditar, repetir y enseñar al equipo.
Cuando Masa probó este patrón en una app pequeña de Next.js con un worker de cola, lo que más ayudó no fue un prompt brillante. Ayudó decidir temprano detalles aburridos: esperar a Postgres, persistir Redis, proteger node_modules, y alinear los comandos de migración y test con CI.
Esta guía crea un ejemplo copiable con app + PostgreSQL + Redis + worker. Compose es excelente para desarrollo local, pruebas de integración y onboarding. Producción es otra decisión: orquestación, secrets, monitoreo, backups, seguridad y coste necesitan una revisión separada.
Arquitectura
flowchart LR
Dev["Developer"] --> App["app: web server"]
App --> Pg["postgres: database"]
App --> Redis["redis: cache and queue"]
Worker["worker: background jobs"] --> Pg
Worker --> Redis
App --> Volume["named volume: node_modules"]
Pg --> PgVol["named volume: postgres_data"]
Redis --> RedisVol["named volume: redis_data"]
app sirve la aplicación web. worker procesa tareas en segundo plano como correos, webhooks, imágenes o jobs de cola. postgres y redis tienen healthchecks para esperar disponibilidad real, no solo que el contenedor exista.
Para la sintaxis oficial, revisa Compose file reference y services reference. También puedes indicarle a Claude Code que use esas referencias para evitar patrones viejos de docker-compose.
Dónde encaja Compose
| Caso | Por qué Compose encaja | Cuidado con |
|---|---|---|
| Desarrollo local | Un comando inicia app, DB, Redis y worker | El rendimiento de mounts cambia por sistema operativo |
| Tests de integración | DB y Redis de prueba se crean bajo demanda | En CI hay que fijar puertos y cache |
| Onboarding | .env.example y make setup reducen pasos | Nunca pongas secrets reales en ejemplos |
| Producción | Puede servir en herramientas internas pequeñas | Requiere revisión de seguridad, recuperación, escala y coste |
La frontera con producción es importante. Compose crea un banco de trabajo igual para cada desarrollador, pero producción debe compararse con ECS, Kubernetes, Cloud Run, Fly.io, Render o la plataforma que ya use tu equipo. Pide a Claude Code una lista de restricciones de migración, no un despliegue automático desde el archivo local.
compose.yaml copiable
El ejemplo asume Node.js o Next.js. Cambia npm run dev, npm run worker:dev y los scripts de migración por los comandos reales de tu package.json.
# compose.yaml
services:
app:
build:
context: .
dockerfile: Dockerfile
target: dev
command: npm run dev -- --hostname 0.0.0.0
ports:
- "3000:3000"
env_file:
- .env
environment:
DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?schema=public
REDIS_URL: redis://redis:6379
volumes:
- .:/workspace
- node_modules:/workspace/node_modules
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "node -e \"fetch('http://127.0.0.1:3000/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))\""]
interval: 10s
timeout: 5s
retries: 12
start_period: 20s
worker:
build:
context: .
dockerfile: Dockerfile
target: dev
command: npm run worker:dev
env_file:
- .env
environment:
DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?schema=public
REDIS_URL: redis://redis:6379
volumes:
- .:/workspace
- node_modules:/workspace/node_modules
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
postgres:
image: postgres:16-alpine
ports:
- "5432:5432"
env_file:
- .env
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- postgres_data:/var/lib/postgresql/data
- ./docker/postgres/init:/docker-entrypoint-initdb.d:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
interval: 5s
timeout: 5s
retries: 10
redis:
image: redis:7-alpine
command: ["redis-server", "--appendonly", "yes"]
ports:
- "6379:6379"
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 10
volumes:
node_modules:
postgres_data:
redis_data:
Tres detalles evitan muchos fallos. Dentro de Compose, los contenedores se encuentran por nombre de servicio: usa postgres:5432 y redis:6379, no localhost. node_modules va en un named volume para que el bind mount del código no pise dependencias instaladas en el contenedor. En el healthcheck de Postgres se usa doble signo de dólar para que la variable se lea dentro del contenedor.
Dockerfile
Un solo Dockerfile con stages de desarrollo, build y producción suele ser más fácil de mantener.
# Dockerfile
# syntax=docker/dockerfile:1
FROM node:22-alpine AS base
WORKDIR /workspace
ENV NEXT_TELEMETRY_DISABLED=1
COPY package*.json ./
RUN npm ci
FROM base AS dev
EXPOSE 3000
CMD ["npm", "run", "dev", "--", "--hostname", "0.0.0.0"]
FROM base AS build
COPY . .
RUN npm run build
FROM node:22-alpine AS production
WORKDIR /workspace
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
COPY package*.json ./
RUN npm ci --omit=dev
COPY --from=build /workspace/.next ./.next
COPY --from=build /workspace/public ./public
USER node
EXPOSE 3000
CMD ["npm", "start"]
El stage dev no copia el código fuente porque Compose lo monta como volumen. El stage build sí copia todo el repositorio para que CI y la imagen de producción no dependan del estado de tu máquina.
.env.example
No subas .env. Sube .env.example con valores de ejemplo y sin credenciales reales.
# .env.example
POSTGRES_USER=app
POSTGRES_PASSWORD=app_password
POSTGRES_DB=app_development
DATABASE_URL=postgresql://app:app_password@postgres:5432/app_development?schema=public
REDIS_URL=redis://redis:6379
NODE_ENV=development
PORT=3000
env_file pasa variables al contenedor. La interpolación del archivo Compose también lee el .env del proyecto. Mantén ambos usos alineados para no crear bugs invisibles.
Makefile y comandos puntuales
Un Makefile pequeño evita instrucciones ambiguas. Si tu equipo no usa make, mueve estos comandos a scripts de package.json.
COMPOSE = docker compose --env-file .env -f compose.yaml
.PHONY: setup up up-d down restart logs ps app-shell db-shell redis-cli migrate seed test lint clean
setup:
cp .env.example .env
$(COMPOSE) build
up:
$(COMPOSE) up --build
up-d:
$(COMPOSE) up -d --build
down:
$(COMPOSE) down
restart:
$(COMPOSE) restart app worker
logs:
$(COMPOSE) logs -f app worker postgres redis
ps:
$(COMPOSE) ps
app-shell:
$(COMPOSE) exec app sh
db-shell:
$(COMPOSE) exec postgres psql -U app -d app_development
redis-cli:
$(COMPOSE) exec redis redis-cli
migrate:
$(COMPOSE) run --rm app npm run db:migrate
seed:
$(COMPOSE) run --rm app npm run db:seed
test:
$(COMPOSE) run --rm app npm test
lint:
$(COMPOSE) run --rm app npm run lint
clean:
$(COMPOSE) down --volumes --remove-orphans
Usa exec para entrar a un contenedor que ya está corriendo. Usa run --rm para comandos puntuales como lint, tests, migraciones o seed. Esa diferencia hace que local y CI se parezcan más.
Prompt de revisión para Claude Code
La guía Claude Code common workflows recomienda dividir el trabajo en tareas concretas: entender, editar, probar y revisar. Haz lo mismo con Compose.
Revisa la configuración Docker Compose de este repositorio.
Archivos:
- compose.yaml
- Dockerfile
- .env.example
- package.json
- workflows de CI si existen
Comprueba:
1. app + postgres + redis + worker pueden ejecutarse localmente
2. healthchecks y depends_on están bien usados
3. named volumes y bind mounts son seguros
4. .env.example no contiene secrets reales
5. existen comandos puntuales para migrate, seed, test y lint
6. riesgos de CI: puertos, cache, permisos y espera de servicios
7. qué revisar antes de llevar este patrón a producción
Restricciones:
- respeta el framework y package manager existentes
- deja los refactors grandes como propuesta
- si editas, explica el motivo y el comando de verificación
Guarda este prompt cerca de CLAUDE.md para repetir el mismo estándar. Para flujos cercanos, lee la guía de Dev Container y la guía de CI/CD.
Casos prácticos
El primer caso es el onboarding del primer día. Si una persona copia .env.example y ejecuta make up, la app, DB, Redis y worker quedan disponibles sin instalar cada servicio a mano.
El segundo caso es probar colas localmente. Correos, procesamiento de imágenes, webhooks de pago y notificaciones suelen vivir en workers. Incluir worker en Compose permite reproducir jobs reales.
El tercer caso es estabilizar tests de integración. Muchas pruebas pasan con un atajo de SQLite y fallan en Postgres. Compose acerca el test a la base de datos real y revela diferencias de SQL, migraciones y cola.
El cuarto caso es revisión de infraestructura con Claude Code. Es fácil no ver un localhost, un volume viejo, un healthcheck ausente o un secret en .env.example. Un prompt reutilizable convierte esa revisión en checklist.
Errores frecuentes
El error más común es conectar desde el contenedor app a localhost. En la red de Compose, los nombres de servicio son los hosts. Usa postgres y redis.
Otro error es creer que depends_on garantiza todo. condition: service_healthy ayuda, pero la app debe reintentar conexiones y el worker no debe ejecutar tareas críticas antes de las migraciones.
Los named volumes antiguos también confunden. Si cambias el esquema y postgres_data sigue ahí, tu estado local puede no coincidir con el repositorio. Usa make clean para una prueba limpia, sabiendo que borra datos locales.
No pongas API keys reales en .env.example. Usa valores como app_password o replace_me, y guarda secrets reales en Docker secrets, un secret manager cloud o el almacén de secrets de CI.
Por último, no conviertas el Compose local en plan de producción sin revisión. Producción exige TLS, exposición de red, backup de DB, persistencia de Redis, monitoreo, escaneo de vulnerabilidades, procedencia de imágenes, permisos y coste.
Formación y plantillas de ClaudeCodeLab
Si quieres adaptar esta base a tu repositorio, empieza por los productos y plantillas de ClaudeCodeLab para estandarizar CLAUDE.md, prompts de revisión y runbooks. Si el problema es adopción de equipo, diferencias de Docker Desktop, CI/CD, permisos o decidir dónde termina Compose y empieza la orquestación de producción, usa la página de training and consultation.
Referencias oficiales: Docker Compose, Compose file reference, services reference y Claude Code common workflows.
Después de probar el contenido de este artículo, el proyecto de prueba de Masa pudo levantar app, Postgres, Redis y worker con make up, y los healthchecks redujeron la carrera típica en la que la app arranca antes de la base de datos. El punto delicado fueron los named volumes antiguos: pueden hacer que una migración parezca rota o arreglada por la razón equivocada. La conclusión práctica es que Compose es una base fuerte para desarrollo local, mientras que producción necesita una revisión separada de seguridad, operación, recuperación y coste.
PDF gratis: cheatsheet de Claude Code
Introduce tu email y descarga una hoja con comandos, hábitos de revisión y flujos seguros.
Cuidamos tus datos y no enviamos spam.
Sobre el autor
Masa
Ingeniero enfocado en workflows prácticos con Claude Code.
Artículos relacionados
Workflow de Obsidian a CLAUDE.md con Claude Code
Convierte notas de trabajo de Obsidian en notas operativas de CLAUDE.md para no repetir contexto.
Claude Code Revenue CTA Routing: de artículos a PDF, Gumroad y consulta
Un flujo con Claude Code para dirigir lectores a PDF gratis, Gumroad o consulta según intención.
Reglas de handoff para equipos con Claude Code: evidencia, permisos, rollback e ingresos
Formato práctico para entregar trabajo de Claude Code con pruebas, permisos, rollback, PDF gratis, Gumroad y consulta.