Docker Compose
Opinionated conventions for consistent, maintainable Docker Compose files.
Best Practices
File naming and override strategy
- •Prefer
compose.yaml(orcompose.yml) as the canonical base file. - •Keep local-only changes in
compose.override.yaml(auto-merged by Compose).- •If an override file is local-only, add it to
.gitignoreunless the team explicitly wants it committed (optionally keep a.examplefile).
- •If an override file is local-only, add it to
- •For environment-specific configs, use
compose.<env>.yamland combine with-f. - •Avoid the top-level
versionkey (obsolete).
Service naming and identity
- •Use kebab-case service names; they become internal DNS names.
- •Avoid
container_nameunless strictly required; it prevents scaling. - •Pin image tags (avoid
latest); prefer digests for production.
Env var conventions
- •Use
.envfor interpolation,env_filefor container runtime values. - •Keep secrets out of Compose files; commit
.env.exampleonly. - •Prefer mapping style for
environmentwhen values include special chars. - •If the same variable is set in both,
environmentoverridesenv_file(key order does not change behavior).
Ports, volumes, and paths
- •Quote
HOST:CONTAINERport mappings to avoid YAML base-60 parsing issues. - •Prefer relative bind mounts starting with
./. - •Use named volumes for persistent data.
Readiness and dependencies
- •Use
depends_onfor ordering; addhealthcheckandcondition: service_healthyfor readiness-sensitive dependencies.
Profiles for optional services
- •Use
profilesto gate optional services (e.g., debug, seed, admin) instead of maintaining separate files. - •If a service is profile-gated, any
depends_ontargets must be in the same profile or always enabled; otherwise the model is invalid.
Project naming and file composition
- •Set top-level
namewhen you need stable project identifiers (network/volume names) across directories or CI. - •Use
include/fragmentsto split large Compose files, but only if your Compose implementation supports them.
DRY with extensions and anchors
- •Use
x-extension fields plus YAML anchors/merge to share repeated blocks (env, volumes, labels) across services.
Secrets and configs
- •Declare
secrets/configsat top level and explicitly grant access per service; top-level declaration alone is not enough. - •Prefer
secrets/configsfor sensitive or shared files when the platform supports them.
Deploy portability
- •Treat
deployas platform-specific; some Compose implementations ignore it in local runs. - •Document when
deployis required so users do not assume it applies everywhere.
Init for PID 1
- •Set
init: truefor long-running services to handle PID 1 signal and zombie reaping correctly.
Ordering Conventions
Top-level order
- •
name(optional) - •
services - •
networks - •
volumes - •
configs - •
secrets
Service key order
Use this exact order for keys within each service to keep the file consistent.
- •Identity:
image/build,container_name,hostname - •Runtime:
command,entrypoint,restart - •Environment:
env_file,environment,labels - •Resources:
ports,expose,volumes - •Connectivity:
depends_on,networks,network_mode - •Health:
healthcheck
Validation
- •Always run
docker compose configbefore shipping changes.
References
- •For the official specification and detailed semantics, see https://compose-spec.io