diff --git a/DevOidcToolkit.Documentation/docs/health-checks.md b/DevOidcToolkit.Documentation/docs/health-checks.md new file mode 100644 index 0000000..3d4745e --- /dev/null +++ b/DevOidcToolkit.Documentation/docs/health-checks.md @@ -0,0 +1,58 @@ +# Health Checks + +Dev OIDC Toolkit exposes health check endpoints that can be used by container orchestrators (such as Docker, Kubernetes, +or Docker Compose) to determine when the service is live and ready to accept traffic. + +## Endpoints + +| Endpoint | Description | +|---|---| +| `GET /healthz/live` | Liveness probe — returns `200 Healthy` when the application process is running. | +| `GET /healthz/ready` | Readiness probe — returns `200 Healthy` when the application is ready to serve requests, including verifying database connectivity when SQLite is configured. | + +Both endpoints return a plain-text body of `Healthy` and an HTTP `200` status code when healthy, or `503 Unhealthy` +when a check fails. + +### Readiness and database checks + +When the application is configured to use a SQLite database (via `Database.SqliteFile`), the `/healthz/ready` endpoint +also verifies that the database is reachable. The `/healthz/live` endpoint never checks the database — it only +reports whether the process itself is running. + +When using the default in-memory database, both endpoints behave identically. + +## Docker HEALTHCHECK + +The official Docker image already includes a `HEALTHCHECK` instruction that uses `curl` to poll `/healthz/live` every +30 seconds: + +```dockerfile +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD curl -f http://localhost:8080/healthz/live || exit 1 +``` + +No extra configuration is required to enable this — it works out of the box. + +## Docker Compose example + +You can use the readiness endpoint to make dependent services wait until Dev OIDC Toolkit is healthy before starting: + +```yaml +services: + dev-oidc-toolkit: + image: ghcr.io/businesssimulations/dev-oidc-toolkit + ports: + - "8080:8080" + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8080/healthz/ready"] + interval: 10s + timeout: 3s + retries: 5 + start_period: 5s + + my-app: + image: my-app + depends_on: + dev-oidc-toolkit: + condition: service_healthy +``` diff --git a/DevOidcToolkit.Documentation/docs/index.md b/DevOidcToolkit.Documentation/docs/index.md index 5a7f7e4..cf46416 100644 --- a/DevOidcToolkit.Documentation/docs/index.md +++ b/DevOidcToolkit.Documentation/docs/index.md @@ -6,3 +6,4 @@ OpenID Connect identity provider for development and testing. - [Tutorial](tutorial.md) - [Configuration](configuration.md) - [Runtime Management](runtime-management.md) +- [Health Checks](health-checks.md) diff --git a/DevOidcToolkit/DevOidcToolkit.csproj b/DevOidcToolkit/DevOidcToolkit.csproj index 64d5b58..8e0bc80 100644 --- a/DevOidcToolkit/DevOidcToolkit.csproj +++ b/DevOidcToolkit/DevOidcToolkit.csproj @@ -24,6 +24,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all + diff --git a/DevOidcToolkit/Program.cs b/DevOidcToolkit/Program.cs index bfd46b9..9a55f05 100644 --- a/DevOidcToolkit/Program.cs +++ b/DevOidcToolkit/Program.cs @@ -115,6 +115,13 @@ .DisableTransportSecurityRequirement(); }); +var healthChecksBuilder = builder.Services.AddHealthChecks(); + +if (config.Database.SqliteFile is not null) +{ + healthChecksBuilder.AddDbContextCheck(tags: ["ready"]); +} + builder.Services.AddControllersWithViews().AddRazorRuntimeCompilation(); builder.Services.AddRazorPages().AddRazorRuntimeCompilation(); @@ -298,6 +305,12 @@ } +app.MapHealthChecks("/healthz/live", new Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions +{ + Predicate = check => !check.Tags.Contains("ready") +}); +app.MapHealthChecks("/healthz/ready"); + app.MapControllers(); app.MapRazorPages(); diff --git a/Dockerfile b/Dockerfile index a420df8..29854bd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -34,8 +34,13 @@ FROM mcr.microsoft.com/dotnet/aspnet:10.0 WORKDIR /app COPY --from=build /app/dist . +RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/* + ENTRYPOINT ["dotnet", "dev-oidc-toolkit.dll"] ENV DevOidcToolkit__Port=8080 ENV DevOidcToolkit__Address=0.0.0.0 EXPOSE 8080 + +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD curl -f http://localhost:${DevOidcToolkit__Port}/healthz/live || exit 1 diff --git a/README.md b/README.md index eaf93b3..0326ff0 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ identity provider such as Keycloak as part of your testing pipeline. - List configured clients - Different levels of logging to help with debugging - Built in documentation +- Health check endpoints (`/healthz/live` and `/healthz/ready`) for container orchestration - Distributed as a self-contained binaries - Distributed as Docker images