Deploying ASP.NET Core Apps: Docker, Linux Hosting, Nginx, and Health Checks

2 minute read

Published:

This post covers practical deployment patterns for ASP.NET Core apps: Docker images, Linux hosting, reverse proxies such as Nginx, and health checks. Deployment is part of application design. An app that cannot start, stop, report health, and receive traffic cleanly is not production-ready.

Publishing the app

The basic publish command:

dotnet publish src/Store.Api/Store.Api.csproj -c Release -o publish

This creates deployable output with compiled assemblies, dependencies, and configuration files.

Use Release builds for deployment:

dotnet publish -c Release

Debug builds are for local development.

Dockerfile

A typical multi-stage Dockerfile:

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish src/Store.Api/Store.Api.csproj -c Release -o /app/publish

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "Store.Api.dll"]

Build and run:

docker build -t store-api .
docker run -p 8080:8080 store-api

In containers, configuration usually comes from environment variables or mounted secrets, not edited files inside the image.

Linux hosting

ASP.NET Core runs well on Linux. Common hosting options:

  • systemd service on a VM
  • Docker container
  • Kubernetes
  • platform services such as Azure App Service or AWS ECS

For systemd, your service file usually starts the published app and restarts it on failure.

Reverse proxy with Nginx

In many Linux deployments, Nginx sits in front of Kestrel.

Nginx handles:

  • TLS termination
  • public ports
  • request forwarding
  • compression
  • buffering
  • static assets in some setups

Basic reverse proxy shape:

server {
    listen 80;
    server_name api.example.com;

    location / {
        proxy_pass http://127.0.0.1:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

In ASP.NET Core, enable forwarded headers when running behind a proxy:

app.UseForwardedHeaders();

Health checks

Health checks let platforms know whether the app is alive and ready.

builder.Services.AddHealthChecks();

var app = builder.Build();

app.MapHealthChecks("/health");

For production, consider separate endpoints:

  • liveness: process is running
  • readiness: app can serve traffic

Readiness may include database, cache, or message broker checks, but be careful not to make health checks too expensive.

Deployment checklist

Use this baseline:

  • publish Release builds
  • externalize configuration
  • expose a health endpoint
  • log to stdout in containers
  • set resource limits
  • validate reverse proxy headers
  • automate deployment through CI/CD

Common mistakes to avoid

Watch for these issues:

  • building Docker images with secrets baked in
  • running Debug builds in production
  • missing health checks
  • ignoring graceful shutdown
  • forgetting forwarded headers behind Nginx or load balancers

Deployment quality affects reliability directly. Treat startup, shutdown, logs, configuration, and health checks as part of the app contract.


Next Article: CI/CD with GitHub Actions for .NET: Build, Test, Publish, Secrets, and Environments