dockerdocker-compose

Docker Compose Environment Variables Not Loading Correctly from .env File


I have a setup of the docker-compose.production.yml in this way:

services:
  web:
    build: .
    command: uvicorn main:app --host ${HOST} --port ${PORT}
    ports:
      - "${PORT}:${PORT}"
    env_file:
      - .env.production
    environment:
      - APP_NAME=${APP_NAME}
      - ENVIRONMENT=${ENVIRONMENT}
      - HOST=${HOST}
      - PORT=${PORT}
      - DEBUG=${DEBUG}

and i have setup the .env.production as:

APP_NAME=FastAPI App Production
ENVIRONMENT=production
HOST=0.0.0.0
PORT=8000
DEBUG=false

and while trying to run:

docker-compose -f docker-compose.production.yml up --build

I am getting the error as:

docker-compose -f docker-compose.production.yml up --build time="2024-08-17T18:58:24+05:45" level=warning msg="The "HOST" variable is not set. Defaulting >to a blank string." time="2024-08-17T18:58:24+05:45" level=warning msg="The "PORT" variable is not set. Defaulting >to a blank string." time="2024-08-17T18:58:24+05:45" level=warning msg="The "PORT" variable is not set. Defaulting to a blank string." time="2024-08-17T18:58:24+05:45" level=warning msg="The "PORT" variable is not set. Defaulting to a blank string." time="2024-08-17T18:58:24+05:45" level=warning msg="The "APP_NAME" variable is not set. Defaulting to a blank string." time="2024-08-17T18:58:24+05:45" level=warning msg="The "ENVIRONMENT" variable is not set. Defaulting to a blank string." time="2024-08-17T18:58:24+05:45" level=warning msg="The "HOST" variable is not set. Defaulting to a blank string." time="2024-08-17T18:58:24+05:45" level=warning msg="The "PORT" variable is not set. Defaulting to a blank string." time="2024-08-17T18:58:24+05:45" level=warning msg="The "DEBUG" variable is not set. Defaulting to a blank string." no port specified: :

However when I specify the environment file directly in the command, it is working.

docker-compose --env-file .env.production -f docker-compose.production.yml up --build

Solution

  • environment has precedence over env_file. so you gave the env_file to the docker container and then immediately overrode those same settings with the (unset) values of of the same name in the docker compose environment.

          - PORT=${PORT}
    

    docker-comose didn't have PORT set, so this evaluates to

          - PORT=
    
    

    --env-file fixes this by providing the values from the .env file to the docker compose environment. Then the interpolation of the same value works to set environment overriding env_file. But that's terribly redundant.

    Just remove environment and you won't need to do anything else, it will just work:

    services:
      web:
        build: .
        command: uvicorn main:app --host ${HOST} --port ${PORT}
        ports:
          - "${PORT}:${PORT}"
        env_file:
          - .env.production