01
Reproduce with one non-secret variable
Create a new directory containing the Compose file below, a .env file with APP_MODE=from-dotenv, and runtime.env with APP_MODE=from-env-file. The Python process prints only APP_MODE; it does not enumerate the container environment.
The apparent duplication is intentional. The environment mapping gets its value while Compose resolves the model. That mapping then competes with the service env_file value when the container is created.
services:
app:
image: python:3.12-slim
env_file: runtime.env
environment:
APP_MODE: ${APP_MODE:?APP_MODE is required}
command: ["python", "-c", "import os; print(os.environ['APP_MODE'])"]02
Identify the stage that chose the value
With no APP_MODE exported in the shell, the reproduction prints from-dotenv. Export APP_MODE=from-shell for the Compose invocation and it prints from-shell. In both runs, the explicit environment mapping wins over the same variable in runtime.env.
This is why editing runtime.env appears ineffective: the selected value comes from another input before the container runs. A .env interpolation file is not automatically a request to inject every one of its variables into every container.
# Run from the new example directory.
printf 'APP_MODE=from-dotenv\n' > .env
printf 'APP_MODE=from-env-file\n' > runtime.env
env -u APP_MODE docker compose run --rm --no-deps app
APP_MODE=from-shell docker compose run --rm --no-deps app
# A run-specific override selects another value.
APP_MODE=from-shell docker compose run --rm --no-deps -e APP_MODE=from-cli app03
Inspect the resolved model safely
For this toy configuration, compare just the APP_MODE entry in the resolved model. docker compose config can print more than this single value, including sensitive settings in a real project. Keep the diagnostic output scoped.
The rendered model represents the settings Compose intends to apply. It does not prove an already running container was recreated, nor can it show whether the application later overrides the variable with a configuration file or command-line flag.
docker compose config --format json | python3 -c 'import json,sys; print(json.load(sys.stdin)["services"]["app"]["environment"]["APP_MODE"])'
docker compose config --quiet04
Choose one intended owner for the variable
If runtime.env should own APP_MODE, remove the competing APP_MODE entry from environment. If the caller should choose it through interpolation, keep the mapping and document the expected shell or --env-file input. A required-value expression is useful when an empty value must stop configuration rather than silently start the application.
Avoid changing unrelated variables to fix this one. Also distinguish CLI --env-file, which supplies model interpolation values, from the service env_file field used for container variables. Similar names do not make them interchangeable.
05
Recreate and verify the application path
For a long-running service, apply the configuration change with docker compose up --detach --no-deps SERVICE, then query only the relevant non-secret value inside the recreated service. A plain restart does not recreate a container with new environment settings.
Our controlled runs produced from-dotenv, from-shell, and from-cli in that order. The observed values matched the intended precedence changes without rebuilding Python or altering the image. If the final process still behaves differently, inspect its own configuration-loading order next.
Sınırları bil
The reproduction uses a non-secret APP_MODE value and Docker Compose CLI. It does not cover Swarm interpolation, application-specific dotenv loaders, or build-time ARG handling. Do not paste full environment or resolved deployment output into tickets when it may contain credentials. Reproduction checked on 26 October 2026 using Linux containers on Docker Engine 29.6.2 and Compose 5.3.1; this is the validation environment, not a minimum-version claim.
Kaynaklar ve ileri okuma
CoreTrailKit tarafından hazırlanan teknik yayın.
Bütün yazıları keşfet