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