-
-
Notifications
You must be signed in to change notification settings - Fork 1
Compose Variable Interpolation
${VAR} references inside compose.yml are substituted the way docker compose does, before wip
looks at the file at all. This is what lets user: ${USER_ID}:${GROUP_ID} reach wslc already
resolved instead of literally.
Applies to mode: compose-native only — under
mode: compose the external tool does its own interpolation.
| Form | Behavior |
|---|---|
${VAR} |
the value, or an empty string if unset |
$VAR |
same as ${VAR}
|
${VAR:-default} |
default if VAR is unset or empty
|
${VAR-default} |
default only if VAR is unset (an empty value stays empty) |
$$ |
an escaped literal $
|
services:
app:
image: myapp:${TAG:-dev}
user: "${USER_ID}:${GROUP_ID}"
environment:
RAILS_ENV: ${RAILS_ENV:-development}
PROMPT: "cost: $$5" # → cost: $5${VAR:?error} and ${VAR:+alternate} aren't recognized. Unlike an unset ${VAR} (which becomes
an empty string), these pass through completely untouched, braces and all:
environment:
MODE: ${MODE:+production} # the container literally sees ${MODE:+production}If you were relying on :? to enforce a required variable, that check won't happen — use
wip doctor plus a sane :- default instead.
Two sources, merged, with the host shell winning:
.env (next to wip.yml, or --env-file) < the process environment
That's Compose's own precedence rule. Using the same .env file wip passes to containers means
interpolation and container env never see two different files. See Env Files.
# .env
TAG=devwip up -d # image: myapp:dev
TAG=ci wip up -d # image: myapp:ci (shell wins)Note this is the opposite direction from container env, where wip.yml's env: beats .env and
the host shell isn't consulted at all.
Values only, never mapping keys — Compose documents the same restriction. And substitution happens after YAML parsing, on the already-parsed structure, which means a substituted value can never introduce YAML syntax:
NOTE=hello # not a commentenvironment:
NOTE: ${NOTE} # the whole string survives, "#" includedStrings inside nested mappings and arrays are all covered.
compose.yml is parsed with aliases enabled, so anchors and merge keys work. A self-referential
alias is rejected rather than recursing until the stack blows:
compose.yml contains a self-referential YAML alias
Re-using the same anchor from several places is fine — that's a shared node, not a cycle.
wip configprints the resolved services, post-interpolation. If a value came out empty, the variable was unset
in both the shell and .env.
Introduction
Modes
Configuration
- Configuration Reference
- Config File Discovery
- Dependencies
- Networking
- Interactions
- Restart Policies
- Env Files
- Secret Masking
- Dockerignore
- Shadow Build Context
- Source Sync
- Sync Modes
compose.yml support
- Compose File Support
- Compose Build
- Compose Depends On
- Compose Profiles
- Compose Variable Interpolation
Commands
- CLI Command Reference
- wip init
- wip version
- wip doctor
- wip config
- wip build
- wip up
- wip stop
- wip down
- wip exec
- wip run
- wip shell
- wip logs
- wip sync
- wip dispatch
- Global Options
- Debug Output
- TTY Allocation
Guides
- Guides
- Migrating from dip
- Reusing an Existing compose.yml
- Fixing a Slow Boot
- Continuous Sync
- Auto Restarting Containers
- Multi Arch Images
- Using wip in CI
Troubleshooting
- Troubleshooting & FAQ
- FAQ
- Configuration Errors
- WSLC Not Found
- Registry Authentication
- Architecture Mismatch
- Volume Limit Reached
- rsync Not Found
- Reporting Issues
Comparison
Project