Microsoft Docs

.NET Core Documentation

Implementing Docker Health Checks in .NET Core

Ensuring your containerized applications are healthy is crucial for reliable deployments. Docker provides a built-in health check mechanism that allows you to define how Docker determines if your container is running and functional. This guide explains how to implement health checks for your .NET Core applications.

What are Docker Health Checks?

A Docker health check is a command that Docker runs periodically inside your container. Based on the exit status of this command, Docker marks the container as:

Docker can then use this health status to perform actions like restarting unhealthy containers or preventing traffic from being sent to them.

Implementing Health Checks in .NET Core

The most common and recommended way to implement health checks in .NET Core applications is by using the Microsoft.Extensions.Diagnostics.HealthChecks NuGet package.

1. Install the NuGet Package

First, add the package to your .NET Core project:

dotnet add package Microsoft.Extensions.Diagnostics.HealthChecks.AspNetCore

2. Configure Health Checks in Startup.cs (or `Program.cs` for .NET 6+)

You need to register the health check services and map an endpoint for Docker to query.

For .NET 5 and earlier (Startup.cs):

// In ConfigureServices method
services.AddHealthChecks();

// In Configure method
app.UseRouting();
app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health"); // The endpoint Docker will poll
});

For .NET 6 and later (Program.cs):

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddHealthChecks(); // Register health check services

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}

app.UseRouting();

app.MapHealthChecks("/health"); // Map the health check endpoint

app.MapGet("/", () => "Hello World!"); // Example endpoint

app.Run();

3. Add Custom Health Checks (Optional but Recommended)

While the basic setup checks if your application is running, you often need to check the health of external dependencies like databases, caches, or external APIs.

Create a custom health check by implementing the IHealthCheck interface:

using Microsoft.Extensions.Diagnostics.HealthChecks;
using System.Threading;
using System.Threading.Tasks;

public class MyDatabaseHealthCheck : IHealthCheck
{
    public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        bool isHealthy = CheckDatabaseConnection(); // Implement your actual DB check
        if (isHealthy)
        {
            return Task.FromResult(HealthCheckResult.Healthy("A healthy result."));
        }
        else
        {
            return Task.FromResult(HealthCheckResult.Unhealthy("An unhealthy result.", exception: new System.Exception("Could not connect to the database.")));
        }
    }

    private bool CheckDatabaseConnection()
    {
        // Simulate a database connection check
        // In a real application, you would try to establish a connection
        // or execute a simple query.
        return true; // Replace with actual logic
    }
}

Register your custom health check:

// In ConfigureServices method (or Program.cs builder.Services)
services.AddHealthChecks()
    .AddCheck<MyDatabaseHealthCheck>("Database"); // Name the check "Database"

You can also add checks for specific dependencies directly:

// Example for SQL Server
services.AddHealthChecks()
    .AddSqlServer("YourConnectionString", name: "Database");

// Example for Redis
services.AddHealthChecks()
    .AddRedis("YourRedisConnectionString", name: "Cache");

Advanced Configuration

The MapHealthChecks method accepts options to configure timeout, presence of status codes, and readiness checks. For readiness checks (used with Kubernetes), you'd typically map a different endpoint.

Configuring Dockerfile

To leverage the .NET Core health checks, you need to configure Docker's HEALTHCHECK instruction in your Dockerfile.

# Use an appropriate base image
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app

# ... other build steps ...

# Copy your published application
COPY /publish .

# Expose the port your application runs on
EXPOSE 80

# Define the health check
# Make sure your application is running and accessible on port 80
# The CMD instruction might be different depending on your setup
HEALTHCHECK --interval=30s --timeout=10s --start-period=15s --retries=3 CMD curl -f http://localhost:80/health || exit 1

Important Note on Health Check Endpoint

The CMD in the HEALTHCHECK instruction should execute a command that returns an exit code of 0 if healthy. Using curl against the /health endpoint is a common and effective pattern.

Testing Health Checks

After building your Docker image and running the container, you can inspect its health status using:

docker ps

Look for the STATUS column. It will show (healthy) or (unhealthy).

You can also view detailed health check logs using:

docker inspect --format='{{json .State.Health}}' <container_id>

Best Practices

  • Keep health checks lightweight and fast.
  • Check critical dependencies, not just application startup.
  • Use appropriate start-period to allow your application time to initialize.
  • Configure retries to avoid false positives due to transient network issues.
  • Consider separate health and readiness checks if using orchestrators like Kubernetes.