The Simplest Reverse Proxy for ASP.NET Core Using Docker

In my earlier post about hosting an ASP.NET core application in docker for production use I fudged a little bit in terms of what it means to production-worthy. Using the dotnet run command starts the web application on the Kestral web server. Kestral is a fine web server for development and maybe production use in an intranet environment but should not be exposed to the internet in a production environment.

You need a reverse proxy. Microsoft has two pages of documentation about this.

  1. Host ASP.NET Core on Linux with Apache
  2. Host ASP.NET Core on Linux with Nginx

The titles for these pages are misleading since the web app is not hosted by Nginix (or Apache). The ASP.NET Core application is running in Kestral and the reverse proxy server is in front managing the requests, logging, SSL termination, etc. Additionally this documentation is neither simple nor straightforward.

Here what follows is THE most painless way for setting up a reverse proxy server for an ASP.NET Core application server running in a docker container.

Overall you need to spin up two additional docker containers. First container is the reverse-proxy server itself, based on nginx. Second container is optional and manages the SSL cerficates from letsencrypt. Documentation for both containers is quality. I followed exactly.

(1) Start the Reverse Proxy Container

docker run -d -p 80:80 -p 443:443 \
--name nginx-proxy \
-v /opt/https_certs:/etc/nginx/certs:ro \
-v /etc/nginx/vhost.d \
-v /usr/share/nginx/html \
-v /var/run/docker.sock:/tmp/docker.sock:ro \
--label com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy \
jwilder/nginx-proxy

(This command is slightly different if you have purchased an SSL certificate separately. See the documentation)

(2) Start the Certificate Management Container

#docker run -d \
--name nginx-letsencrypt \
--volumes-from nginx-proxy \
-v /opt/https_certs:/etc/nginx/certs:rw \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-e NGINX_PROXY_CONTAINER=nginx-proxy \
jrcs/letsencrypt-nginx-proxy-companion

(3) Add a few environment variables to the docker-compose file for your ASP.NET Core web application

web:
environment:
- VIRTUAL_HOST=myrazorapp.glenmccallum.com
- LETSENCRYPT_HOST=myrazorapp.glenmccallum.com
- LETSENCRYPT_EMAIL=glen.mccallum@protonmail.com
expose:
- "5000"
image: glenmccallum/myrazorapp:latest
restart: always

(4) Start the container for your Web Application

docker compose up -d

(5) Wait for the magic to happen

It might take a while for the certificate management container to get the SSL certificate fetched and configured for your web application.

If  you’re impatient here are a couple of other commands to check on things.

# check on certificate status
docker exec nginx-letsencrypt /app/cert_status
# renew the SSL certificate(s) manually
docker exec nginx-letsencrypt /app/force_renew

BONUS: These containers will support/redirect multiple applications for domains/subdomains on the same host.