Dokploy Monitoring#
dokploy-monitoring is a Go application that collects host system metrics (CPU, memory, disk, network) and per-container metrics from remote servers, stores them in a local SQLite database, and POSTs threshold alerts back to the main Dokploy server. It runs as a Docker container (dokploy/monitoring:latest or :canary) and is deployed once per registered remote server via monitoring-setup.ts.
Configuration#
All configuration is passed as a single JSON blob in the METRICS_CONFIG environment variable . The Go app loads it once at startup via GetMetricsConfig(), which uses sync.Once to parse and validate the JSON . Fatal errors are raised if token or urlCallback are missing.
The config schema is defined in two places that must stay in sync:
- Go:
Configstruct inapps/monitoring/config/metrics.go - TypeScript:
metricsConfigjsonb column inpackages/server/src/db/schema/server.ts
Key fields :
| Field | Default | Description |
|---|---|---|
server.type | "Remote" | "Dokploy" (local) or "Remote" |
server.refreshRate | 60 | Seconds between metric collections |
server.port | 4500 | HTTP port the Go app listens on |
server.token | "" | Bearer token for auth |
server.urlCallback | "" | tRPC endpoint for threshold alerts |
server.retentionDays | 2 | Days to retain metric rows |
server.cronJob | "" | Cron expression for cleanup |
server.thresholds.cpu | 0 | CPU alert threshold (%) |
server.thresholds.memory | 0 | Memory alert threshold (%) |
containers.refreshRate | 60 | Seconds between container metric collections |
containers.services.include | [] | Allowlist of container names to monitor |
containers.services.exclude | [] | Denylist of container names |
Validation schema (TypeScript/Zod): apiUpdateServerMonitoring β refreshRate min 2, port min 1, retentionDays min 1, cronJob min 1 char, urlCallback must be a valid URL.
Initialization & Startup Sequence#
The main() function boots the application in this order:
- Load
.envβgodotenv.Load()(no-op if absent) - Parse config β
config.GetMetricsConfig()readsMETRICS_CONFIG - Init SQLite β
database.InitDB()opensmonitoring.dbat/app/monitoring.db - Start cleanup cron β
database.StartMetricsCleanup(db, retentionDays, cronExpression)schedules periodic deletion of stale rows - Start Fiber HTTP server β listens on
server.port(default3001if 0) - Start container monitor β
containers.NewContainerMonitor(db).Start()begins periodicdocker statscollection - Start server metrics goroutine β ticker fires every
refreshRateseconds, callsmonitoring.GetServerMetrics(), saves to DB, then callsmonitoring.CheckThresholds()
HTTP API#
All routes except /health require bearer-token auth via middleware.AuthMiddleware() .
| Route | Params | Description |
|---|---|---|
GET /health | β | Returns {"status":"ok"} (unauthenticated) |
GET /metrics | ?limit=N|all (default 50) | Host system metrics from SQLite |
GET /metrics/containers | ?appName=&limit=N|all | Container metrics; returns [] if appName is empty |
Lifecycle Management#
Deployment (Server Setup)#
setupMonitoring(serverId) is called from serverSetup() β currently only in the cloud-hosted path β after generating a fresh auth token and callback URL. It:
- Creates
/etc/dokploy/monitoring/monitoring.dbon the remote server viaexecAsyncRemote - Pulls
dokploy/monitoring:latest(or:canaryin dev/non-latest) - Force-removes any existing
dokploy-monitoringcontainer - Creates and starts a new container with
RestartPolicy: always
The monitoring container runs with NetworkMode: "host" and these bind mounts :
| Host path | Container path | Mode |
|---|---|---|
/var/run/docker.sock | /var/run/docker.sock | read-only |
/sys | /host/sys | read-only |
/etc/os-release | /etc/os-release | read-only |
/proc | /host/proc | read-only |
/etc/dokploy/monitoring/monitoring.db | /app/monitoring.db | read-write |
setupWebMonitoring() is a parallel function for the local (web server) monitoring instance, using the same pattern but calling pullImage/execAsync instead of their remote equivalents, and without NetworkMode: "host".
Cleanup / Retention#
StartMetricsCleanup schedules a cron job using github.com/robfig/cron. On each tick, CleanupMetrics deletes rows older than retentionDays from both container_metrics and server_metrics tables using a UTC RFC3339 cutoff timestamp. The cron handle is stopped via defer cleanupCron.Stop() on process exit .
Threshold Alerts#
The Go CheckThresholds() function compares live CPU/memory metrics against configured thresholds, then POSTs an AlertPayload to server.urlCallback. The callback target is the tRPC endpoint notification.receiveNotification on the main Dokploy server . The Node.js side dispatches the alert to all configured notification channels (Discord, Slack, Teams, Telegram, etc.) via sendServerThresholdNotifications().
Key Source Files#
| File | Purpose |
|---|---|
apps/monitoring/main.go | Entry point: startup, HTTP routes, goroutines |
apps/monitoring/config/metrics.go | Config struct and METRICS_CONFIG loader |
apps/monitoring/database/cleanup.go | Retention cleanup cron |
packages/server/src/setup/monitoring-setup.ts | Container deployment for remote and local servers |
packages/server/src/setup/server-setup.ts | Token generation + setupMonitoring() call site |
packages/server/src/db/schema/server.ts | metricsConfig DB schema and Zod validators |