PalBo
PalBo

Reputation: 2612

Environment variable not being set in Dockerfile

I have a project with 2 Dockerfiles, one for backend and one for database. The dockerfiles are in separate folders. I build the two images with a docker-compose.yml file that looks like this:

version: "3.7"
services:
  dotnet-backend:
    container_name: dotnet-backend
    build: .
    env_file: .env
    links:
      - mssql-db
    ports:
      - "8000:80"
  mssql-db:
    container_name: mssql-db
    build: ./Database
    env_file: .env
    volumes:
     - ./Database/:/scripts/
    ports:
      - "1433:1433"
    expose:
      - "1433"
    command:
      - /bin/bash
      - -c 
      - |
        /opt/mssql/bin/sqlservr &
        sleep infinity

As you can see, I use a .env file for environment variables, this file is located in the src folder, same as the Dockerfile for the backend and the rest of the backend code.

This is my Dockerfile for backend:

FROM mcr.microsoft.com/dotnet/core/sdk:3.0 AS build-env
WORKDIR /app

# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore

# Copy everything else and build
COPY . ./
RUN dotnet publish -c Debug -o out MyProject.csproj

# Build runtime image
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0
WORKDIR /app
COPY --from=build-env /app/out .

EXPOSE 80

ENV ASPNETCORE_ENVIRONMENT=$ASPNETCORE_ENVIRONMENT

ENTRYPOINT ["dotnet", "MyProject.dll"]

This is my Dockerfile for the database (located in ./Database):

FROM mcr.microsoft.com/mssql/server:2017-latest

ENV ACCEPT_EULA=Y
ENV SA_PASSWORD=$SA_PASSWORD
ENV MSSQL_PID=Developer
ENV MSSQL_TCP_PORT=1433 

WORKDIR /src
COPY ./ /scripts/

EXPOSE 1433 

RUN (/opt/mssql/bin/sqlservr --accept-eula & ) | grep -q "Service Broker manager has started" && sleep 5s && (for foo in /scripts/*.sql;do /opt/mssql-tools/bin/sqlcmd -S127.0.0.1 -Usa -P$SA_PASSWORD  -i$foo;done)

And finally my .env file:

SA_PASSWORD=SomePassword
ASPNETCORE_ENVIRONMENT=Development
ConnectionStrings__My_db=Data Source=tcp:mssql-db,1433;Initial Catalog=DevDB;User ID=sa;Password=SomePassword

What's strange is that the ASPNETCORE_ENVIRONMENT variable gets set, as I can tell by testing my API that it is running in development mode, and the connection string from the .env file also gets set as my API can connect to my database when I manually enter the password. But the SA_PASSWORD environment variable does not get set. Here is the output from the docker-compose up --build command:

enter image description here

So why are the other variables and connection strings getting set, but not the password? Everything works fine if I replace ENV SA_PASSWORD=$SA_PASSWORD with ENV SA_PASSWORD=SomePassword in the database Dockerfile.

Upvotes: 3

Views: 14819

Answers (2)

Al-waleed Shihadeh
Al-waleed Shihadeh

Reputation: 2855

you don't need to set the env vars in the docker images at all, and you can fix the issue using the changes below

ASPNETCORE_ENVIRONMENT works because the app only check it at runtime and not at build time

database docker file

FROM mcr.microsoft.com/mssql/server:2017-latest

ENV ACCEPT_EULA=Y
ENV MSSQL_PID=Developer
ENV MSSQL_TCP_PORT=1433

WORKDIR /src
COPY ./ /scripts/

EXPOSE 1433 

COPY ./docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]

docker-entrypoint.sh (chmod a+x)

#!/bin/bash -e


(/opt/mssql/bin/sqlservr --accept-eula & ) | grep -q "Service Broker manager has started" && sleep 5s && (for foo in /scripts/*.sql;do /opt/mssql-tools/bin/sqlcmd -S127.0.0.1 -Usa -P$SA_PASSWORD  -i$foo;done)

exec "$@"

exit 0

app docker file

FROM mcr.microsoft.com/dotnet/core/sdk:3.0 AS build-env
WORKDIR /app

# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore

# Copy everything else and build
COPY . ./
RUN dotnet publish -c Debug -o out MyProject.csproj

# Build runtime image
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0
WORKDIR /app
COPY --from=build-env /app/out .

EXPOSE 80

ENTRYPOINT ["dotnet", "MyProject.dll"]

you can move also these to the env file and it is recommended to separate the env files for the containers

ENV ACCEPT_EULA=Y
ENV MSSQL_PID=Developer
ENV MSSQL_TCP_PORT=1433

Upvotes: 1

matiferrigno
matiferrigno

Reputation: 950

That isn't a valid way to take a var from environment.

The variable $SA_PASSWORD in Dockerfile is actually a var into scope of Dockerfile and build image time.

The var hasn't value because the way of assign it, is through ARG command (https://docs.docker.com/engine/reference/builder/#arg).

Everyway, if you need declare a SA_PASSWORD and read it of environment at container runtime, you must do it trough ENTRYPOINT. ENTRYPOINT is executed when container launch.

Upvotes: 0

Related Questions