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 on8080. - db — an optional
mssql/server:2022container for the monitor's own metadata storage. If you already have a SQL Server for that, delete thedbservice and thedepends_onblock and pointAPP_DB_CONNECTIONat your existing server. - volumes —
dp-keys(DataProtection key ring) andmssql-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-keysvolume — the DataProtection key ring (auth cookies; any legacyenc:v1values). Losing it just logs users out and regenerates the cert; it does not lose connection strings, because those use the fixedEncryption:Key(built-in or yourENCRYPTION_KEY). Seedocs/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.jsonis excluded from the image via.dockerignore; production runs useASPNETCORE_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.