-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Description
Description
Today, Docker Compose variable interpolation substitutes strings before schema validation. When a field is typed as boolean (like services..depends_on..required), using ${VAR} causes a validation error because Compose sees a string, not a boolean:
validating compose.yaml: services.postgresql.depends_on.grafana.required must be a boolean
This prevents toggling optional dependencies via env vars—an otherwise common and very useful pattern.
Why this matters
depends_on.*.required is a boolean with default true (introduced around v2.20.x). It’s perfect for making a dependency optional when a service is gated by a flag or profile. But you can’t drive it from an env var today without preprocessing.
Docker Documentation
Compose officially supports env-var interpolation from .env, shell, and --env-file, but the current behavior doesn’t allow those values to be typed when the schema expects booleans.
Docker Documentation
+1
Profiles are great (and we use them), but there are many real cases where you want a single compose file and a simple ENABLE_X=true/false switch, especially for CI jobs and local toggles.
Docker Documentation
Minimal Reproducer
.env
ENABLE_GRAFANA=true
compose.yaml
services:
grafana:
image: grafana/grafana:latest
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:3000/api/health || exit 1"]
postgresql:
image: postgres:17
depends_on:
grafana:
condition: service_healthy
required: ${ENABLE_GRAFANA:-false} # ← want boolean from envRun
docker compose config
Actual
validating compose.yaml: services.postgresql.depends_on.grafana.required must be a boolean
Expected
With ENABLE_GRAFANA=true → required: true
With ENABLE_GRAFANA=false or unset → required: false
Proposal(s)
Any of the following would solve it without breaking existing configs:
Boolean coercion for typed fields
After interpolation, if a field is schema-typed as boolean, treat "true"/"false" (case-insensitive) as booleans; otherwise error.
Opt-in cast syntax
Add a cast operator for interpolation, e.g. ${ENABLE_GRAFANA?bool} (or ${{ bool(ENABLE_GRAFANA) }}), producing a true boolean, not a string.
Honor YAML tag casts post-interpolation
Allow required: !!bool ${ENABLE_GRAFANA:-false} to be parsed as boolean. Currently this still errors because validation happens before/without a cast being applied.
Backward compatibility
Coerce only when the schema type is boolean; do not coerce in environment: (those are strings). This avoids historic yes/no pitfalls and keeps behavior predictable. Docs can note accepted values are exactly true|false.
Docker Documentation
Environment
Docker Compose: v2.34.0 (repro also reported by others since v2.20.x)
OS: Linux (x86_64)
Compose file uses the current Compose Specification. depends_on.required boolean is documented in service reference.
Docker Documentation
Related docs
Interpolation: how env vars are injected into Compose files.
Docker Documentation
Profiles: recommended for optional services (workaround, not a direct fix).
Docker Documentation
Service reference (notes required default/behavior).
Docker Documentation
Impact
This unlocks simple, single-file toggles such as:
Optional observability stack (ENABLE_GRAFANA, ENABLE_PROMTAIL)
Optional seed/init jobs (REQUIRE_BOOTSTRAP)
Feature-gated infra bits in CI (USE_MINIO, USE_LOCAL_REGISTRY)
Thanks for considering! Happy to test a PR or nightly build.