Docker

SQL Server Health Monitor ships as a plain ASP.NET Core web app, so it runs well in a Linux container. On Linux the UseWindowsService() call is a no-op — the app is a normal console web host.

There is no separate settings page for deployment configuration: everything is supplied through environment variables (the standard ASP.NET Core config source). The content configuration — which servers to monitor, alert rules, notification channels — is stored in the database and managed through the existing UI, not through env vars.

Quick start

cp .env.example .env      # fill in SA_PASSWORD + APP_DB_CONNECTION
docker compose up -d --build

Then open http://localhost:8080. On first run you'll be redirected to /Account/Setup to create the admin account (unless you seeded ADMIN_EMAIL/ADMIN_PASSWORD).

The app applies its EF Core migrations automatically on startup (DatabaseSettings:EnableAutomaticMigrations defaults to true), so the schema is created in an empty database on first boot.

What the compose file contains

  • app — built from the repo Dockerfile, serves HTTP on 8080.
  • db — an optional mssql/server:2022 container for the monitor's own metadata storage. If you already have a SQL Server for that, delete the db service and the depends_on block and point APP_DB_CONNECTION at your existing server.
  • volumes — dp-keys (DataProtection key ring) and mssql-data (database files).

Configuration (environment variables)

Nested config keys use __ (double underscore) as the separator.

Variable Purpose
ConnectionStrings__DefaultConnection The monitor's own metadata database. Required. (compose maps APP_DB_CONNECTION to this)
SecuritySettings__RequireHttps false behind a TLS-terminating proxy (see below).
SecuritySettings__BindHttps false in containers — otherwise the app binds HTTPS with a self-signed cert.
DataProtection__KeyFolder Path for the key ring; mount a volume (compose uses /keys).
Encryption__Key Optional 32-byte base64 override for secret encryption. Empty = built-in key.
InitialAdmin__Email / InitialAdmin__Password Optional non-interactive first admin.
Authentication__Oidc__* Optional SSO (see docs/sso.md).

Monitored-server connection strings and notification secrets are not set via env — you add those in the UI, and they're stored encrypted in the database.

HTTPS / reverse proxy

appsettings.json ships with RequireHttps and BindHttps set to true (sensible for the Windows/MSI deployment). In a container you almost always terminate TLS at a reverse proxy (nginx, Traefik, Caddy, an ingress) and run the app on plain HTTP, so the compose file sets both to false. If you leave BindHttps=true, the app generates a self-signed certificate into the key folder and binds SecuritySettings:HttpsPort (default 8443) instead of 8080.

Persistence — what to back up

  • The database — all servers, rules, history, users.
  • The dp-keys volume — the DataProtection key ring (auth cookies; any legacy enc:v1 values). Losing it just logs users out and regenerates the cert; it does not lose connection strings, because those use the fixed Encryption:Key (built-in or your ENCRYPTION_KEY). See docs/backup-and-restore.md.

If you set your own ENCRYPTION_KEY, treat it like a password and keep it with the database backup — without it the encrypted connection strings can't be read.

Building the image directly (without compose)

docker build -t sqlhealthmonitor .
docker run -d -p 8080:8080 \
  -e ConnectionStrings__DefaultConnection="Server=host.docker.internal,1433;Database=SqlHealthMonitor;User Id=sa;Password=...;TrustServerCertificate=True" \
  -e SecuritySettings__RequireHttps=false \
  -e SecuritySettings__BindHttps=false \
  -e DataProtection__KeyFolder=/keys \
  -v sqlhealth-keys:/keys \
  sqlhealthmonitor

Health checks

The app exposes /health and /health/detailed. Point your orchestrator's liveness/ readiness probes at /health. (The base image has no curl, so a container HEALTHCHECK using curl won't work out of the box — probe from the orchestrator or add a tool to the image if you need an in-container check.)

Notes

  • appsettings.Development.json is excluded from the image via .dockerignore; production runs use ASPNETCORE_ENVIRONMENT=Production.
  • msdb-based features (SQL Agent jobs, backup history) are skipped automatically against Azure SQL Database / AWS RDS targets — unrelated to how the monitor itself is hosted.