Docker Compose "variable is not set. Defaulting to a blank string" in CI
Compose interpolates ${VAR} from the environment and .env. When a referenced variable is unset it warns and substitutes an empty string - which can silently produce a bad image tag, a :latest fallback, or an invalid value that breaks up.
What this error means
A docker compose up prints WARN[...] The "TAG" variable is not set. Defaulting to a blank string, then pulls/builds the wrong image (e.g. myorg/api: resolving to :latest) or fails on an empty port/path. Locally it works because the shell or .env had the value.
WARN[0000] The "TAG" variable is not set. Defaulting to a blank string.
# image: myorg/api:${TAG} -> myorg/api: (empty tag pulls :latest or fails)Common causes
The variable is unset in the CI environment
Compose reads ${VAR} from the process environment and an .env file in the project dir. In CI neither may define it, so it interpolates to empty.
No .env file present on the runner
A .env that exists locally but is gitignored or not generated in CI means the variables it provided are missing.
No default in the interpolation
Using ${TAG} instead of ${TAG:-default} gives no fallback, so an unset variable becomes blank rather than a safe default.
How to fix it
Provide the variable or a default
Set the variable in the job, or use Compose’s default-value syntax.
# set it explicitly in CI:
TAG=1.4.2 docker compose up -d
# or give a safe default in the compose file:
# image: myorg/api:${TAG:-1.4.2}Pass an explicit env file and require the value
Point Compose at an env file and fail fast if a required variable is missing.
docker compose --env-file ci.env config # renders interpolated values
# fail early on a required var:
: "${TAG:?TAG must be set}"How to prevent it
- Use
${VAR:-default}or${VAR:?required}instead of bare${VAR}. - Pass an explicit
--env-filein CI rather than relying on a local.env. - Validate interpolation with
docker compose configbeforeup.