dockergodocker-compose

empty env variable lunching os.Getenv with docker run, populated with docker compose


I created a webserver in Go and tried to create a docker image for the purpose of learning. When I start the docker image it doesn't detect any environment variables with "docker run", but if I launch "docker compose" I can see them populated, what am I missing? I do not understand

main.go:

func init() {
    fmt.Println("Inizializziamo...")
    cmd := exec.Command("env")
    stdout, err := cmd.Output()
    if err != nil {
        fmt.Println(err.Error())
        return
    }

    // Print the output
    fmt.Println(string(stdout))
}

docker-compose.yml

services:
  blog:
    build: .
    ports:
      - "8080:8080"
    environment:
      - DB_HOST=db
      - DB_PORT=5432
      - DB_USER=test_user
      - DB_PASSWORD=psw
      - DB_NAME=mydb
      - PORT=8080
    depends_on:
      - db

  db:
    image: postgres:15
    restart: always
    environment:
      - POSTGRES_USER=test_user
      - POSTGRES_PASSWORD=psw
      - POSTGRES_DB=mydb
    ports:
      - "5432:5432"
    volumes:
      - db-data:/var/lib/postgresql/data

volumes:
  db-data:

# docker compose run --rm blog env
[+] Creating 1/0
 ✔ Container mywebserver-db-1  Running                                                                                                                                                                                                                                   0.0s 
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=154d98c6277d
TERM=xterm
DB_PASSWORD=psw
DB_NAME=mydb
PORT=8080
DB_HOST=db
DB_PORT=5432
DB_USER=test_user
HOME=/root

with docker run no env variables

# docker run xxxx/mywebserver
Inizializziamo...
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=0f42e93ff038
HOME=/root

am I doing something wrong? Thanks for the help


Solution

  • The difference in behavior between docker run and docker compose is because the environment variables specified in your docker-compose.yml file are not automatically applied when you use docker run. They are only applied when you use docker compose to manage your containers.

    Why it happens

    Fixing it for docker run

    If you want to replicate the behavior of docker compose with docker run, you need to pass the environment variables manually. For example:

    docker run -p 8080:8080 \
      -e DB_HOST=db \
      -e DB_PORT=5432 \
      -e DB_USER=test_user \
      -e DB_PASSWORD=psw \
      -e DB_NAME=mydb \
      -e PORT=8080 \
      xxxx/mywebserver
    

    Alternatively, you can define the environment variables in an .env file and use the --env-file flag with docker run. Example:

    .env file:

    DB_HOST=db
    DB_PORT=5432
    DB_USER=test_user
    DB_PASSWORD=psw
    DB_NAME=mydb
    PORT=8080
    

    Command:

    docker run --env-file .env -p 8080:8080 xxxx/mywebserver
    

    Key Points to Remember

    1. docker run does not read docker-compose.yml: This is why you see different behavior.
    2. Environment variables need to be explicitly passed: Use -e or --env-file to specify them.
    3. Prefer docker compose for complex setups: If your setup requires multiple services and environment variables, docker compose is easier to manage.

    Using docker compose is recommended for scenarios like yours since it simplifies the process of managing multi-container applications.