Understand Docker environment variable precedence

Separate image defaults, container configuration, Compose interpolation, and process-local changes when a variable has an unexpected value.

Best practices
Illustration of container operations and troubleshooting

A container receives its initial environment when it is created. Runtime configuration can override an image's ENV defaults, but docker run and Docker Compose are separate launch paths: their options do not form one combined override chain.

Follow the launch path you actually use

For a direct Docker launch:

docker run --rm -e MODE=runtime-value alpine:3.22 printenv MODE

An explicit -e MODE=value overrides that image's default for MODE. -e MODE without a value asks Docker to take the variable from the client environment; it is not equivalent to an explicit empty string.

In Compose, a service's environment overrides its service-level env_file, and both override image defaults. A one-off docker compose run -e override has the highest precedence for that run. Interpolated values also depend on where Compose obtains the substitution value, so distinguish the final container environment from the inputs used to render the file.

services:
  app:
    image: alpine:3.22
    env_file: ./app.env
    environment:
      MODE: compose-value
    command: ["printenv", "MODE"]

Here, MODE from app.env is replaced by compose-value. Running docker compose run --rm -e MODE=one-off app replaces it for that one-off container, without reconfiguring an already running service.

Keep interpolation separate from injection

Compose can read a .env file or a CLI --env-file to resolve ${VAR} in its configuration. The shell environment also participates in that lookup. Finding a value there does not automatically insert every variable into every container.

Service-level env_file: supplies container environment entries. environment: can supply literal or interpolated entries. Their similar names describe different jobs. File discovery and relative paths depend on Compose's project and command-line settings; do not assume every invocation reads one fixed working-directory file.

Scope ARG and ENV correctly

ARG ALPINE_VERSION=3.22
FROM alpine:${ALPINE_VERSION}
ARG ALPINE_VERSION
ENV APP_BASE_VERSION=${ALPINE_VERSION}

The argument declared before FROM can select the base image. Redeclaring it after FROM brings it into that stage's scope. The explicit ENV then stores a runtime default. An ARG does not automatically become a container environment variable, although build arguments can affect generated files, image metadata, and provenance.

Neither ARG nor ENV is a suitable mechanism for build secrets. Use supported build secret mounts. Runtime secrets need a deliberate file, secret-store, or orchestration integration; environment values can be visible through inspection and other authorized access.

Inspect the correct layer

docker compose config
docker inspect --format '{{json .Config.Env}}' myapp
docker exec myapp printenv MODE

These commands can reveal secrets, so limit their output and handling. Compose shows resolved configuration; inspect shows the container's creation environment; exec starts a new process using its applicable environment.

An entrypoint's export affects the application it subsequently launches. It does not modify Docker's stored configuration or automatically appear in a later exec process. Diagnose the application's effective configuration through a safe application-specific mechanism when that distinction matters.

Apply changes and encode values

Changing an environment file does not update an existing process. Recreate the service with docker compose up -d after changing its resolved configuration; use --force-recreate if an intentional recreation is otherwise not detected. A restart alone keeps the existing container environment.

Environment entries are strings. Define an application-specific representation for lists or structured settings, or use a configuration file. Dynamic entrypoint calculations are valid when exported before exec launches the application, but should not be mistaken for a daemon-wide environment update.

See Compose environment precedence and Docker build variables.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting