Environment variable not being set in Dockerfile - docker

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.

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

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.

Related

Nuxt Docker: Exit code 0

I am building a Dockerfile for my Nuxt app. Whenever the container starts it gets exited with error code 0 immediately.
Here is my Dockerfile:
# Builder image
FROM node:16-alpine as builder
# Set up the working directory
WORKDIR /app
# Copy all files (Nuxt app) into the container
COPY ../frontend .
# Install dependencies
RUN npm install
# Build the app
RUN npm run build
# Serving image
FROM node:16-alpine
# Set up the working directory
WORKDIR /app
# Copy the built app
COPY --from=builder /app ./
# Specify the host variable
ENV HOST 0.0.0.0
# Expose the Nuxt port
ENV NUXT_PORT=3000
EXPOSE 3000
CMD ["npm", "run", "start"]
my docker-compose.yml file has:
frontend:
container_name: frontend
build:
context: .
dockerfile: ./docker/nuxt/Dockerfile
ports:
- "3000:3000"
networks:
- app-network
When I try to see the log file of the container, it only shows this.. which doesn't help me.
> frontend#1.0.0 start
> nuxt start
OK, I needed to add .dockerignore file
frontend/.nuxt/
frontend/dist/
frontend/node_modules/

Cannot assign requested address (localhost:xxxx) - Docker + Linux Containers

We have a WPF application that will call a Web API called API-1 which is running in a docker container. I also have another API called API-2 which is also running in a docker but a different container.
Whenever the API-1 call happened from the application, the API-1 will do some logic and try to do a post request to API-2.
Now, my problem is, the post request to API-2 always returns Cannot assign requested address (localhost:XXXX).
If I try without docker, it works fine.
Also, a separate request to each of the API works fine (using POSTMAN)
This problem occurs only if the API deployed in the docker. I was using docker-compose to create the containers. I have created a docker network bridge and allocated it to the respective APIs in the docker-compose.yml file.
Here is my docker-compose file as well as the docker file for both of the APIs.
Docker-Compose.yml
version: "3.7"
networks :
localdev:
name: localdev
external: true
services:
api-01:
build:
context: .
dockerfile: api-01/Dockerfile
restart: always
container_name: "api-01"
ports:
- "8082:80"
environment:
ASPNETCORE_ENVIRONMENT: "Development"
networks:
- localdev
api-02:
build:
context: .
dockerfile: api-02/Dockerfile
restart: always
container_name: "api-02"
ports:
- "8083:80"
environment:
ASPNETCORE_ENVIRONMENT: "Development"
networks:
- localdev
DockerFile(API-1)
FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS build
WORKDIR /src
COPY ["api-01/api-01.csproj", "api-01/"]
COPY ["CommonEntities/CommonEntities.csproj", "CommonEntities/"]
RUN dotnet restore "api-01/api-01.csproj"
COPY . .
WORKDIR "/src/api-01"
RUN dotnet build "api-01.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "api-01.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "api-01.dll"]
DockerFile(API-2)
FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS build
WORKDIR /src
COPY ["api-02/api-02.csproj", "api-02/"]
COPY ["CommonEntities/CommonEntities.csproj", "CommonEntities/"]
RUN dotnet restore "api-02/api-02.csproj"
COPY . .
WORKDIR "/src/api-02"
RUN dotnet build "api-02.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "api-02.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "api-02.dll"]
I'm not sure what I'm missing here!
I have tried most of the solutions from the internet, but nothing works.
It looks like I need to use {DOCKER_IP} instead of "localhost" if I want to have communication between two API in two different containers.
After I changed my post request to hit "http://{My_PC_IP_Address}:8082", the request was successful.
Thanks to David for redirecting me to the right documentation https://docs.docker.com/network/bridge/

Getting OAuth settings from env var with full stop in key

I am using docker linux container to run my servicestack application and I need to be able to read the OAuth keys from environment variables defined in my docker-compose.yml.
It appears impossible to do this due to the full stop in the variable name.
For example in OAuthProvider.cs (https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/Auth/OAuthProvider.cs) line 26:
this.ConsumerKey = appSettings.GetString($"oauth.{oAuthProvider}.{consumerKeyName}");
It is reading for example the key oauth.google.ConsumerKey.
Linux doesn't support full stops in environment variables. Using the debugger I can see that if I put the variables in like:
environment:
- oauth.RedirectUrl=http://example.com
- oauth.CallbackUrl=http://example.com/auth/{0}
- oauth.basecamp.ConsumerKey=fgshghfdhfghgfdhf
- oauth.basecamp.ConsumerSecret=fdghfdghdfghgdfhdfghfgd
Then they are removed. I did some research and this is common issue, if the env var has a full stop then it gets removed. I cannot find any workaround for this.
Do you have any idea how I can pass these hard coded settings with docker environment variable?
Here is representation of my entire dockerfile for reference:
ARG BUILD_MODE=Release
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
RUN apt-get update && apt-get install openssh-server unzip -y
RUN curl -sSL https://aka.ms/getvsdbgsh | /bin/sh /dev/stdin -v latest -l ~/vsdbg
COPY sshd_config /etc/ssh/
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["Project/Project.csproj", "Project/"]
COPY ["Project.ServiceModel/Project.ServiceModel.csproj", "Project.ServiceModel/"]
COPY ["Project.ServiceInterface/Project.ServiceInterface.csproj", "Project.ServiceInterface/"]
COPY ["NuGet.config", "NuGet.config"]
RUN dotnet restore "Project/Project.csproj"
COPY . .
WORKDIR "/src/Project"
RUN dotnet build "Project.csproj" -c "$BUILD_MODE" -o /app/build
FROM build AS publish
RUN dotnet publish "Project.csproj" -c "$BUILD_MODE" -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT service ssh start && echo "root:$SSH_PASSWORD" | chpasswd && dotnet Project.dll
And this is docker-compose:
version: "3.7"
services:
project:
build:
context: E:\project\
dockerfile: E:\project\project\Dockerfile
image: project:local
ports:
- "57008:80"
- "57009:443"
- "57001:2222"
restart: always
depends_on:
- "db"
environment:
- oauth.RedirectUrl=http://example.com
- oauth.CallbackUrl=http://example.com/auth/{0}
- oauth.basecamp.ConsumerKey=fgshghfdhfghgfdhf
- oauth.basecamp.ConsumerSecret=fdghfdghdfghgdfhdfghfgd
db:
image: postgres:10.9
restart: always
environment:
POSTGRES_PASSWORD: fdgdfgdfgdf
POSTGRES_USER: project
ports:
- "5445:5432"
You can provide your own custom AppSettings provider or use the DictionarySettings and populate it with a mapped environment variable that's suitable to use in Docker, e.g:
Use underscore separators in Docker:
environment:
- oauth_RedirectUrl=http://example.com
- oauth_CallbackUrl=http://example.com/auth/{0}
- oauth_basecamp_ConsumerKey=fgshghfdhfghgfdhf
- oauth_basecamp_ConsumerSecret=fdghfdghdfghgdfhdfghfgd
Then create a new Dictionary AppSettings using the keys ServiceStack expects, e.g:
string env(string key) =>
Environment.GetEnvironmentVariable(key.Replace(".","_"));
var envSettings = new DictionarySettings(new Dictionary<string,string> {
["oauth.RedirectUrl"] = env("oauth.RedirectUrl"),
["oauth.CallbackUrl"] = env("oauth.CallbackUrl"),
["oauth.basecamp.ConsumerKey"] = env("oauth.basecamp.ConsumerKey"),
["oauth.basecamp.ConsumerSecret"] = env("oauth.basecamp.ConsumerSecret"),
});
Then use that in your Auth Providers, e.g:
new MyAuthProvider(envSettings)

unable to run a net core docker container

After refactoring from docker-compose into separate Docker file for each project, I'm Unable to run the container, it simply exits. I'm using both docker and docker-compose since I'll have more projects down the road.
My docker files are as follows.
docker-compose.yml
version: '3'
services:
customer:
image: customer
container_name: customer
build:
context: ./Customer
dockerfile: Dockerfile
Customer/Dockerfile
FROM mcr.microsoft.com/dotnet/core/runtime:2.2
WORKDIR /Customer
EXPOSE 80
COPY ./bin/Release/netcoreapp2.2/ service/
ENTRYPOINT ["dotnet", "service/Customer.dll"]
Also I had this within docker-compose file before. How do I map 6001 to 80 within Dockerfile?
ports:
- 6001:80
Attempt 2
FROM mcr.microsoft.com/dotnet/core/sdk:2.2
WORKDIR /Customer
ENV DATABASE_HOST=database
ENV DATABASE_NAME=db
ENV DATABASE_USER=sa
ENV DATABASE_PASSWORD=Password
EXPOSE 80
COPY . .
CMD dotnet build
ENTRYPOINT ["dotnet", "Customer/bin/Release/netcoreapp2.2/Department.dll"]
Attempt 3
copied from main site.
Copied from here https://docs.docker.com/engine/examples/dotnetcore/
FROM mcr.microsoft.com/dotnet/core/sdk:2.2 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 Release -o out
# Build runtime image
FROM mcr.microsoft.com/dotnet/core/aspnet:2.2
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "aspnetapp.dll"]
Did you mean to run dotnet SDK commands? Please install dotnet SDK
from: https://go.microsoft.com/fwlink/?LinkID=798306&clcid=0x409
Here is a lazy and basic docker file. I added some comments and some helpful build/debug options, e.g: "RUN ls -al" to list the current directory. Just like a linux VM.
# step 1 - building you app with SDK as base image
FROM microsoft/dotnet:2.2-sdk AS build-env # call the environment build
WORKDIR /build # create a work dir
COPY . . # you don't need copy everything to build your app, but this is for simplisity
RUN ls -al # linux command to list dir content
RUN cd /Customer && dotnet publish -o out # actually building the app and publishing to /out dir
RUN cd /Customer && ls -al # navigate to the folder you copied and list dir
FROM microsoft/dotnet:2.2-aspnetcore-runtime AS runtime # step 2, runtime env (slimmed down container)
WORKDIR /app # create workdir
COPY --from=build-env /<YOUR_BULD_PATH>/out ./ # copy from prev container build output
RUN ls -al # list again
ENTRYPOINT ["dotnet", "Department.dll", "--urls", "http://*:6001"] # example from .NET Core 2.2 webapi with port 6005, this might not be your case
Now to run the docker-compose, just point out the docker file like you have already done. But both docker/docker-compose should work just fine now. Ofcourse you need to tweak the docker file a bit, i dont know your app or folder structure.
And just a tip, if you want to run your docker file as stand alone, dont forget the args when you start it to map ports --> -p 6001:80

docker-compose error when running netcore-react app

When I build my app without using docker-compose :
docker build -t aspnetapp .
docker run -d -p 8080:80 --name myapp aspnetapp
the docker container runs just fine. But when I try to run it, using docker-compose up, the image builds successfully but the website gives me errors on loading.
dockerfile:
FROM microsoft/dotnet:sdk AS build-env
WORKDIR /app
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -
RUN apt-get install -y nodejs
# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore
# Copy everything else and build
COPY . ./
RUN dotnet publish -c Release -o out
# Build runtime image
FROM microsoft/dotnet:aspnetcore-runtime
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "app.dll"]
docker-compose:
version: '3.4'
services:
app:
image: aspnetapp
build: ./app
ports:
- "8080:80"
AggregateException: One or more errors occurred. (One or more errors occurred. (Failed to start 'npm'. To resolve this:.
[1] Ensure that 'npm' is installed and can be found in one of the PATH directories.
Current PATH enviroment variable is: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Make sure the executable is in one of those directories, or update your PATH.
removing
environment: - ASPNETCORE_ENVIRONMENT=Development
from the compose.override file fixed all this. I'm not sure why it's the problem.
Is your Dockerfile in ./ or ./app? If it's in ./ change docker-compose.yml to build: ./
EDIT
I've just realised that you are specifying both image and build in your docker-compose.yml; get rid of the image.

Resources