.NET, Docker & SSL

DevOps
Published May 6, 2022 ยท 3 min read
In this article, we will go over how to run a .NET docker container with a free self-signed generated SSL certificate over HTTPS

Prerequisite

This tutorial assumes that:

  • you already have a .NET project under development. It is preferred to be .NET 6, but feel free to choose any other version as long as you make sure to configure the versions in the Dockerfile
  • you have access to a UNIX machine (WSL also works)

Containerizing .NET Project

The first thing we need to do is configure our project to run in a container. We will be using docker for this.

To do so, we need to add a file named "Dockerfile" (with no extension) at the level of the project:

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["Solution/Project.csproj", "Solution/"]
RUN dotnet restore "Solution/Project.csproj"
COPY . .
WORKDIR "/src/Solution"
RUN dotnet build "Project.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "Project.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Project.dll"]

One thing to notice in the first part of the above file (lines 1 to 4) is that we are exposing two ports: 80 (for HTTP requests) and 443 (for HTTPS). Also, make sure to change the base image version if you are not using .NET 6.

In the second part of it (lines 6 to 12), we are building the solution. Notice here that we're using the Docker Builder Pattern. This helps reduce the final image's size, so we only keep what is needed.

In the third part, we are running `dotnet publish`, which prepares our project for deployment.

In the last part, we are copying the result of the previous step, which will constitute our final image's content.

Note: make sure to rename "Solution" and "Project" to your solution and project's names.

We can now build and run our image, however, it will only run over HTTP, because we haven't created an SSL certificate for it yet.

Generating SSL/TLS certificate using Let's Encrypt

Let's Encrypt is a free process to generate an SSL certificate. Note here that their certificates are valid for 90 days only, so you will need to renew them roughly every 3 months.

To generate a certificate, run the following command in your UNIX shell:

docker run --rm -p 80:80 -p 443:443 \
    -v /root/nginx/letsencrypt:/etc/letsencrypt \
    certbot/certbot certonly -d {your_domain} \
    --standalone -m {your_email_address} --agree-tos

The above command runs a container of certbot docker image which generates the certificate. Make sure to change the values of the domain and the email to match yours.

After you run the command, you will get a folder /root/nginx/letsencrypt/live/{your_domain}/ which contains files:

  • cert.pem
  • chain.pem
  • fullchain.pem
  • privkey.pem

These files, together, represent your certificate.

Docker Compose

We will be using docker-compose to orchestrate the container's lifetime. To do so, add the following docker-compose.yml file

version: '3.9'

services:
  dotnet-app:
    build: path/to/dotnet/Dockerfile
    hostname: dotnet
    container_name: dotnet
    ports:
      - "8080:80"
      - "8081:443"
    volumes:
      - ./cert/nginx/letsencrypt/live/{your_domain}:/https/
    environment:
      - ASPNETCORE_URLS=https://+:443;http://+:80
      - ASPNETCORE_Kestrel__Certificates__Default__Path=/https/fullchain.pem
      - ASPNETCORE_Kestrel__Certificates__Default__KeyPath=/https/privkey.pem

Running Docker Compose

Now, to run your project:

docker-compose up -d

You'll project will then run on http://localhost:8080 and https://localhost:8081