Reputation: 2612
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:
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
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
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