Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ENV variables not coming through godotenv Docker

I have a web app written in Go, dockerised and using gomod.

I cannot get it to read environment variables.

Upon running docker-compose up always returns "Error getting env, not comming through"

I'm using godotenv to try do this. Below is my implementation. I cannot for the life of me figure out what's going wrong. If anyone can see something I'm missing you'll be saving a life.

The main.go, .env, docker-compose.yml and Dockerfile are all in the root of the project

main.go

func main() {
    router := mux.NewRouter()

    err := godotenv.Load()
    if err != nil {
        log.Fatalf("Error getting env, not comming through %v", err)
    } else {
        fmt.Println("We are getting the env values")
    }

    fmt.Println(os.Getenv("MY_ENV"))

}

.env

MY_ENV=thisismyenvvariable
DB_HOST=testdata123
DB_DRIVER=testdata123
DB_USER="testdata123"
DB_PASSWORD=testdata123
DB_NAME=testdata123
DB_PORT=5432

docker-compose.yml

version: '3'
services:
  app:
    container_name: template_123
    build: .
    ports: 
      - 8080:8080 
    restart: on-failure
    volumes:
      - api:/usr/src/app/
    env_file:
      - .env
    depends_on:
      - template-postgres          
    networks:
      - template


  template-postgres:
    image: postgres:latest
    container_name: startup_template_golang_db_postgres
    environment:
      - POSTGRES_USER=${DB_USER}  
      - POSTGRES_PASSWORD=${DB_PASSWORD}
      - POSTGRES_DB=${DB_NAME}
      - DATABASE_HOST=${DB_HOST} 
    ports:
      - '5432:5432'
    volumes:
      - database_postgres:/var/lib/postgresql/data
    env_file:
      - .env
    networks:
      - template
    
  pgadmin:
    image: dpage/pgadmin4
    container_name: pgadmin_container
    environment:
      PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL}
      PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD}
    depends_on:
      - template-postgres
    ports:
      - "5050:80"
    networks:
      - template
    restart: unless-stopped

volumes:
  api:
  database_postgres:                  

# Networks to be created to facilitate communication between containers
networks:
  startup_template:
    driver: bridge

Dockerfile

# Start from golang base image
FROM golang:alpine as builder

# ENV GO111MODULE=on

# Add Maintainer info
LABEL maintainer="satoshi123"

# Install git.
# Git is required for fetching the dependencies.
RUN apk update && apk add --no-cache git

# Set the current working directory inside the container 
WORKDIR /app

# Copy go mod and sum files 
COPY go.mod go.sum ./

# Download all dependencies. Dependencies will be cached if the go.mod and the go.sum files are not changed 
RUN go mod download 

# Copy the source from the current directory to the working Directory inside the container 
COPY . .

# Build the Go app
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# Start a new stage from scratch
FROM alpine:latest
RUN apk --no-cache add ca-certificates

WORKDIR /root/

# Copy the Pre-built binary file from the previous stage. Observe we also copied the .env file
COPY --from=builder /app/main .
# COPY --from=builder /app/.env .       

# Expose port 8080 to the outside world
EXPOSE 8080

#Command to run the executable
CMD ["./main"]
like image 636
jpazzajpeg Avatar asked Feb 22 '21 11:02

jpazzajpeg


People also ask

How do I pass environment variables to docker containers?

With a Command Line Argument The command used to launch Docker containers, docker run , accepts ENV variables as arguments. Simply run it with the -e flag, shorthand for --env , and pass in the key=value pair: sudo docker run -e POSTGRES_USER='postgres' -e POSTGRES_PASSWORD='password' ...

Is it possible to pass environment variables using Dockerfiles?

Passing Environment Variables Into a DockerfileDockerfile provides a dedicated variable type ENV to create an environment variable. We can access ENV values during the build, as well as once the container runs. Let's see how we can use it to pass value to our greetings script. There are two different ways to do it.

Do docker container inherit environment variables?

Using docker-compose , you can inherit env variables in docker-compose. yml and subsequently any Dockerfile(s) called by docker-compose to build images. This is useful when the Dockerfile RUN command should execute commands specific to the environment.

How can I see environment variables in container?

Fetch Using docker exec Command Here, we are executing the /usr/bin/env utility inside the Docker container. Using this utility, you can view all the environment variables set inside Docker containers.


Video Answer


1 Answers

If you're already using env_file in your docker_compose.yml, you don't really need godotenv, as the environment is already passed down from docker-compose:

version: '3'

services:
    app:
        image: busybox:latest
        command: sh -c 'echo "Hello $$USER!"'
        env_file:
            - .env
# .env
USER=user1
$ docker-compose up
Recreating test_app_1 ... done
Attaching to test_app_1
app_1  | Hello user1!
test_app_1 exited with code 0

This is a better idea than trying to copy the .env file into the container, because it means you can pass environment variables without having to rebuild the container each time ;)

If you nonetheless want to use godotenv, I found that by simply uncommenting the COPY --from=builder /app/.env . line from your Dockerfile, the .env file gets loaded correctly (as godotenv finds it in the directory, whereas if it were commented it wouldn't).

$ docker-compose up
Starting template_123 ... done
Attaching to template_123
template_123 | We are getting the env values
template_123 | thisismyenvvariable
template_123 exited with code 0

If you want to keep it in sync with your filesystem, you will need to use a volume to link your .env with the one on your filesystem, or as I've said, ditch godotenv altogether as it is not really useful in your case.

like image 166
morganbaz Avatar answered Oct 28 '22 02:10

morganbaz