Skip to main content
Why .env Variables Don't Work in Docker – Separating Build and Runtime Environments

Why .env Variables Don't Work in Docker – Separating Build and Runtime Environments

Why .env Variables Don’t Work in Docker – The Build-Time vs. Runtime Problem

Everything runs perfectly locally – but inside the Docker container certain .env variables are suddenly missing. This problem occurs frequently when applications are run with docker-compose and a Dockerfile together. The cause is almost always the same: environment variables are available in the wrong context.

The Real Problem: Build-Time vs. Runtime Environment

Docker draws a strict distinction between two moments:

  • Build time – the Dockerfile is executed. Only ARG and ENV are available.
  • Run time – the container is started. docker-compose.yml supplies the variables.

And this is exactly where the problem arises: .env variables from docker-compose are NOT carried over into the Dockerfile build phase. That is why it works without trouble locally, while values are missing inside the container.

Why Does It Work Locally but Not in Docker?

Locally, your application can access the .env file directly. Inside the container, by contrast, the file does not exist or sits somewhere else.

The result: the app runs without environment values.

How Docker Handles .env

Many developers believe that Docker Compose automatically carries every value from .env into the container. That is not correct.

Docker Compose uses the .env file exclusively to substitute variables within the Compose file itself:

environment:
  APP_ENV: ${APP_ENV}
    

But:

These values are only available at run time – not in the Dockerfile.

Why You Had to Define Variables in Both the Dockerfile AND docker-compose

This is a typical workaround used when developers are unsure which part runs when.

Example:

# Dockerfile
ENV API_URL=${API_URL}
    

This only works if API_URL is passed in as an ARG.

# Dockerfile
ARG API_URL
ENV API_URL=${API_URL}
    

And then in docker-compose:

build:
  context: .
  args:
    API_URL: ${API_URL}
    

Only now is the variable genuinely available in both worlds.

The Three Reliable Solutions

1. Pass Variables as ARG During the Build

# Dockerfile
ARG APP_URL
ENV APP_URL=${APP_URL}
    
# docker-compose.yml
build:
  args:
    APP_URL: ${APP_URL}
    

2. Copy the .env File into the Container (not recommended!)

Error-prone and insecure — for internal projects only.

3. The Official Recommendation: Set ENV at Run Time Only

If your build does not depend on variables:

environment:
  APP_URL: ${APP_URL}
    

Best Practice: How to Separate Variables Properly

  • Dockerfile → only values that are required during the build
  • docker-compose → every value the app needs at run time

This keeps your setup clean, secure and easy to follow.

Conclusion

The problem can be named precisely: environment variables build-time vs. runtime mismatch.

Once you understand that Docker has two separate worlds, you can pass variables cleanly and correctly – and errors like these become a thing of the past.

Need help with Docker or DevOps? We support you in building stable, secure and optimized container infrastructures.

Why .env Variables Don't Work in Docker – Separating Build and Runtime Environments | BIT62