Agent-almanac setup-compose-stack
install
source · Clone the upstream repo
git clone https://github.com/pjt222/agent-almanac
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/pjt222/agent-almanac "$T" && mkdir -p ~/.claude/skills && cp -r "$T/i18n/wenyan-ultra/skills/setup-compose-stack" ~/.claude/skills/pjt222-agent-almanac-setup-compose-stack-983e22 && rm -rf "$T"
manifest:
i18n/wenyan-ultra/skills/setup-compose-stack/SKILL.mdsource content
Set Up Compose Stack
Configure Docker Compose for multi-service application stacks with databases, caches, and workers.
When to Use
- Running a web app with a database and/or cache
- Setting up a development environment with multiple services
- Orchestrating background workers alongside an API
- Needing reproducible multi-service environments across teams
Inputs
- Required: Application service (language, port, entry point)
- Required: Supporting services needed (database, cache, queue, etc.)
- Optional: Development vs production configuration
- Optional: Existing Dockerfiles for custom services
Procedure
Step 1: Define Core Stack
services: app: build: context: . dockerfile: Dockerfile ports: - "3000:3000" environment: DATABASE_URL: postgres://appuser:apppass@postgres:5432/appdb REDIS_URL: redis://redis:6379 depends_on: postgres: condition: service_healthy redis: condition: service_started restart: unless-stopped postgres: image: postgres:16 environment: POSTGRES_DB: appdb POSTGRES_USER: appuser POSTGRES_PASSWORD: apppass volumes: - pgdata:/var/lib/postgresql/data ports: - "5432:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U appuser -d appdb"] interval: 5s timeout: 5s retries: 5 redis: image: redis:7-alpine ports: - "6379:6379" volumes: - redisdata:/data volumes: pgdata: redisdata:
Expected:
docker compose up starts all services with the app waiting for a healthy database.
Step 2: Add Health Checks
Health checks enable
depends_on with condition: service_healthy:
services: postgres: healthcheck: test: ["CMD-SHELL", "pg_isready -U appuser -d appdb"] interval: 5s timeout: 5s retries: 5 redis: healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 3s retries: 5 app: healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 10s timeout: 5s retries: 3 start_period: 10s
Step 3: Configure Networks
services: app: networks: - frontend - backend postgres: networks: - backend nginx: networks: - frontend ports: - "80:80" networks: frontend: driver: bridge backend: driver: bridge
This isolates the database from direct external access while the app bridges both networks.
Step 4: Manage Environment Variables
Create
.env file (git-ignored):
POSTGRES_PASSWORD=secure_password_here APP_SECRET=your_secret_key
Reference in compose:
services: postgres: environment: POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} app: env_file: - .env
Create
.env.example (committed to git):
POSTGRES_PASSWORD=changeme APP_SECRET=changeme
Step 5: Add Worker Services
services: worker: build: context: . dockerfile: Dockerfile command: ["node", "src/worker.js"] environment: DATABASE_URL: postgres://appuser:apppass@postgres:5432/appdb REDIS_URL: redis://redis:6379 depends_on: postgres: condition: service_healthy redis: condition: service_started restart: unless-stopped deploy: replicas: 2
Step 6: Use Profiles for Optional Services
services: app: # always starts build: . mailhog: image: mailhog/mailhog ports: - "8025:8025" profiles: - dev adminer: image: adminer ports: - "8080:8080" profiles: - dev
# Start core services only docker compose up # Start with dev tools docker compose --profile dev up
Step 7: Create Override for Development
docker-compose.override.yml is auto-merged:
services: app: build: target: dev volumes: - .:/app - /app/node_modules environment: NODE_ENV: development DEBUG: "app:*" command: ["npm", "run", "dev"]
Step 8: Build and Run
# Build all images docker compose build # Start in background docker compose up -d # View logs docker compose logs -f app # Check service status docker compose ps # Stop and remove docker compose down # Stop and remove volumes (full reset) docker compose down -v
Expected: All services start, health checks pass, app connects to database and cache.
On failure: Check
docker compose logs <service>. Common issues: port conflicts, missing environment variables, health check timeouts.
Validation
-
starts all services without errorsdocker compose up - Health checks pass for database and cache
- Application connects to all dependent services
- Named volumes persist data across restarts
-
is git-ignored;.env
is committed.env.example -
cleanly stops everythingdocker compose down - Profiles separate dev tools from production services
Common Pitfalls
- No health checks:
withoutdepends_on
only waits for container start, not readiness.condition: service_healthy - Hardcoded passwords in compose: Use
files or Docker secrets. Never commit passwords..env - Volume mount overwrites: Mounting
overwrites.:/app
built in the image. Use an anonymous volume:node_modules
./app/node_modules - Port conflicts: Check
anddocker compose ps
for conflicts.lsof -i :<port>
key: Compose V2 ignores theversion:
key. Omit it for modern setups.version:- WSL path issues: Use
paths when mounting Windows directories from WSL./mnt/c/...
Related Skills
- R-specific Docker Compose configurationssetup-docker-compose
- write the Dockerfile that compose referencescreate-dockerfile
- build optimized images for the stackcreate-multistage-dockerfile
- add an Nginx reverse proxy to the stackconfigure-nginx