I am currently working on deploying a .NET Core web api on a server. I wanted to do it using docker compose for easy management. In my Startup.cs
I have this code:
public class Startup
{
public Startup (IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices (IServiceCollection services)
{
var databaseHost = Configuration["DB_HOST"] ?? "localhost";
// ........
}
// ........
}
My Dockerfile
is pretty standard, as Microsoft's documentation states it should be:
FROM microsoft/dotnet:sdk 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 microsoft/dotnet:aspnetcore-runtime
WORKDIR /app
COPY --from=build-env /app/out .
EXPOSE 80/tcp
ENTRYPOINT ["dotnet", "ApiProject.dll"]
I define my environment variables in my docker-compose.yml
file:
version: '3'
services:
restapi:
build:
context: ./ApiProject
dockerfile: Dockerfile
depends_on:
- db
ports:
- "5000:80"
restart: always
environment:
- DB_HOST=db
db:
image: postgres
ports:
- "5432:5432"
restart: always
environment:
POSTGRES_USER: "root"
POSTGRES_PASSWORD: "root"
This docker-compose.yml
file works just fine on my local machine. The issue comes when I want to deploy it on the server. Someone online have made a docker-compose file which runs an nginx proxy and containers for automatically retrieving valid SSL certificates using Let's Encrypt (jwilder/nginx-proxy).
It is pretty easy to get it working. When starting a new docker container, you just have to assign it to the correct external docker network (in this case: nginx-proxy
), and then give it the following environment variables:
VIRTUAL_HOST: example.com
LETSENCRYPT_HOST: example.com
LETSENCRYPT_EMAIL: [email protected]
Furthermore, instead of mapping ports, you just have to expose port 80. Then when the container starts up, the other containers will automatically get the SSL certificates and make a proxy to the newly started container.
The issue here is the way Microsoft's containers works with environment variables. The container for my web api has a few environment variables of itself, such as DB_HOST=mydbhost.com
. It then automatically gets imported in the code. That means I can't add the environment variables (i.e. VIRTUAL_HOST: example.com
) needed for the proxy containers to work properly.
I tried out with the following docker-compose.yml
configuration:
version: '3'
services:
restapi:
build:
context: ./EffortlessApi
dockerfile: Dockerfile
depends_on:
- db
expose:
- 80
restart: always
environment:
- DB_HOST=db
- VIRTUAL_HOST: my_domain.com
- LETSENCRYPT_HOST: my_domain.com
- LETSENCRYPT_EMAIL: [email protected]
db:
image: postgres
ports:
- "5432:5432"
restart: always
environment:
POSTGRES_USER: "root"
POSTGRES_PASSWORD: "root"
networks:
default:
external:
name: nginx-proxy
But that resolved in the following error when running docker-compose up
:
ERROR: The Compose file './docker-compose.yml' is invalid because: services.restapi.environment contains {"VIRTUAL_HOST": "api.effortless.dk"}, which is an invalid type, it should be a string
I'm quite lost on how I should solve this issue. I want to easily deploy and manage multiple containers with valid SSL certificates, and this setup is pretty cool, if just it worked with the .NET project as well.
I figured it all out, the solution was luckily pretty simple. I don't know why, but Microsoft for some reason simply chose to format their environment wrong. To fix this, simply use =
rather than :
without the space:
(...)
environment:
- DB_HOST=db
- VIRTUAL_HOST=my_domain.com
- LETSENCRYPT_HOST=my_domain.com
- [email protected]
(...)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With