/deploy — generate all deployment files without starting services.
/deploy --up — generate files and immediately run bash init.sh to start the stack.
Prerequisites
The following must exist before running this skill:
backend/ and/or frontend/ — source code with known runtimes and entry points.
specs/design/deployment.md — deployment architecture decisions (DB engine, port assignments, service names).
project-manifest.json — for service names, port config, and environment variable inventory.
If any of these are missing, stop and report what is absent.
Steps
Step 1 — Read Project Manifest
Read project-manifest.json. Extract:
Service names and their roles (backend API, frontend SPA, worker, etc.)
Port assignments for each service.
Database engine and version.
Any declared environment variable names.
Step 2 — Read Deployment Architecture
Read specs/design/deployment.md. Extract:
Service dependencies and startup order.
Health check endpoints for each service.
Volume requirements (DB data, uploads, etc.).
Any explicit constraints (network mode, resource limits).
Step 3 — Generate docker-compose.yml
Generate docker-compose.yml at the project root from the deployment template.
Requirements:
Every service that another service depends on must use depends_on with a condition: service_healthy entry.
Define named volumes for all persistent data (DB data directory, upload storage).
No hardcoded passwords — all secrets come from environment variables.
Each service must have a healthcheck block with a realistic test, interval, timeout, and retries.
Use specific image tags (e.g., postgres:16-alpine), never latest.
Step 4 — Generate Dockerfiles
backend/Dockerfile
Multi-stage build: builder stage installs dependencies, runtime stage copies only the built artefact.
Run as non-root user.
EXPOSE the port declared in the manifest.
HEALTHCHECK instruction matching the health check endpoint.
frontend/Dockerfile (if frontend exists)
Build stage: install deps, run build.
Serve stage: NGINX or equivalent static server.
EXPOSE the frontend port.
Step 5 — Generate .env.example
Generate .env.example at the project root.
Every environment variable referenced in docker-compose.yml or either Dockerfile must have an entry. Each entry must include a comment explaining what it is and what format it expects:
No variable may appear in compose or Dockerfiles without a corresponding .env.example entry.
Step 6 — Generate init.sh
Generate init.sh at the project root from the init template.
The script must:
Check that Docker and Docker Compose are available.
Copy .env.example to .env if .env does not already exist.
Run docker compose build.
Run docker compose up -d.
Poll each service health check URL until it responds or a timeout is reached (30s per service).
Print a summary: which services are up, which URLs are accessible.
Make init.sh executable (chmod +x init.sh).
Step 7 — Phase Evaluation Gate
This gate runs BEFORE the stack is started — it exists to catch invalid compose syntax, port conflicts, and missing health checks before they become runtime failures.
First, validate syntax deterministically:
docker compose config
Fix any errors before spawning the evaluator.
Then spawn the evaluator agent (artifact mode) to validate deploy artifacts.
Agent invocation:
Spawn Agent with subagent_type="evaluator" and prompt:
Phase: deploy
Artifacts: docker-compose.yml, all Dockerfile* files, .env.example, init.sh
Check: Every service in architecture.md has a compose entry. No port conflicts. Health checks defined. YAML syntax valid.
Write result to specs/reviews/phase-deploy-eval.json
Ratchet loop (max 2 iterations):
If verdict is PASS — proceed to Step 8.
If verdict is FAIL — fix config issues based on findings. Re-run evaluator.
Ratchet rule: weighted_average must be >= previous iteration. Revert on regression.
After 2 iterations — proceed to Step 8 with findings attached as warnings, but do NOT run --up on an unresolved FAIL — report the failure instead.
Step 8 — If --up Flag
Only after the gate above has passed (or warnings were explicitly accepted), run:
bash init.sh
Report the output. If any service fails its health check, print the service logs and stop.
Output
Path
Purpose
docker-compose.yml
Full service stack definition
backend/Dockerfile
Backend container build
frontend/Dockerfile
Frontend container build (if applicable)
.env.example
All required environment variables documented
init.sh
Bootstrap script: build, start, health check
Gotchas
Missing depends_on with health conditions. Services that start before their dependencies are ready cause intermittent failures. Always use condition: service_healthy.
No bind mount volumes. Named volumes persist across docker compose down. Bind mounts to host paths break in CI and on other machines.
Hardcoded passwords. Never put credentials directly in docker-compose.yml. All secrets go in .env.
Missing .env.example entries. New variables added to compose but not documented leave other developers with silent failures.
latest image tags. Tags like postgres:latest break reproducibility. Pin to a specific version.
Root user in containers. Run application processes as a non-root user to limit blast radius on compromise.