compose-standard
Lean local Compose stacks. Not a platform generator.
Scope
Not here: Make wrapper names such as up / down / logs (makefile-standard), image build internals (dockerfile-standard), GitHub Actions (ci-standard), Go layout and golangci (go-project-standard). K8s, Swarm, reverse proxies as a product, and runtime secret distribution are out of scope entirely.
Workflow
1. Inspect needs, not possibilities
Inventory: app entrypoints, existing Compose, Dockerfiles, .env* and README, the DB, cache, or queue the project already uses, Make compose targets, ports. Ignore sidecars nothing points to.
2. Apply standard
Read references/rules.yaml, the source of truth for rule IDs. Full rules: references/compose-standard.md.
Greenfield: adapt a template from assets/ and replace every Adapt… marker. Never ship an unfinished placeholder.
- App alone:
assets/compose.app-only.yaml.template - App plus one data service:
assets/compose.yaml.template
Migrate: references/migration-guide.md, incrementally, dropping unused services, networks, and volumes.
3. YAGNI
Never unconditional: custom networks; multiple overlay files; Redis, Nginx, or adminer by reflex; profiles; deploy: keys; a Swarm or K8s translation; digest pins on every local dependency image.
4. Validate
python3 scripts/validate_compose.py /path/to/compose.yaml
# structural check when Docker is available:
docker compose -f /path/to/compose.yaml config --quiet
Errors = fix. Warnings = human review. A static check is not proof the stack runs.
Validator logic is hardcoded today; the checks: blocks in rules.yaml are illustrative, not executed.
5. Report
- Services included and the evidence for each
- Filename chosen,
compose.yamlor a legacy name kept - Healthcheck and
depends_ondecisions - Env and secrets approach, including any
.env.exampleyou added - Bind mount against named volume choices
- Validation result, what you skipped, exceptions taken
Hard rules
- Prefer
compose.yamlfor greenfield. Keep a legacy name only when callers depend on it. - MUST NOT use the obsolete top-level
version:. - MUST NOT put a secret, password, or token literal in the file. Use
${VAR}orenv_file, and never a${VAR:-secret}default. - Third-party
image:uses a controlled tag, never floatinglatest. - The project app uses
build:. Image internals belong todockerfile-standard. - Where startup order matters:
healthcheckplusdepends_on: condition: service_healthy, or document why not. - Networks, volumes, and profiles only when evidenced.
- Apps must not depend on this repo at runtime.
Exceptions
# compose-standard: except <rule-id> — <reason>
Every ignored MUST needs an exception line with a reason. An ignored SHOULD needs a brief rationale when it is not obvious.