How to monitor multiple Docker hosts from one dashboard
How to get unified visibility across 2-20 Docker servers without running a monitoring stack on each one. Multi-host Docker monitoring explained.
Running multiple Docker servers is common. A web server here, a database server there, maybe a separate machine for background workers. What's less common is having a clean answer to "are all of them healthy right now?" — because the moment you have two servers, you either need to SSH into each one separately or you need a monitoring system that understands multi-host. This guide covers the realistic options for multi-host Docker monitoring and how to get unified visibility without running a monitoring stack on every machine.
The problem: SSH into each server doesn't scale
With one server, docker ps and docker stats are fine. With two servers, you're already switching terminal windows. With five, you're spending more time checking status than being productive.
The "SSH into each server" approach also fails during incidents. If something is wrong at 2 AM, you don't want to be logging into four different servers one at a time to find the broken container. You want to see all your infrastructure in one view and identify the problem immediately.
Option 1: Prometheus federation (powerful, complex)
Prometheus supports federation — a pattern where a central Prometheus scrapes metrics from multiple per-host Prometheus instances.
[Server 1: Prometheus + cAdvisor] ─┐
[Server 2: Prometheus + cAdvisor] ─┤──▶ [Central Prometheus] ──▶ [Grafana]
[Server 3: Prometheus + cAdvisor] ─┘
Each server runs its own Prometheus + cAdvisor + Node Exporter. The central Prometheus uses federation to pull aggregated metrics from each.
# central prometheus.yml
scrape_configs:
- job_name: 'federated_server_1'
honor_labels: true
metrics_path: '/federate'
params:
match[]:
- '{job="cadvisor"}'
- '{job="node"}'
static_configs:
- targets:
- 'server1.example.com:9090'
- job_name: 'federated_server_2'
honor_labels: true
metrics_path: '/federate'
static_configs:
- targets:
- 'server2.example.com:9090'
The catch: Each server needs Prometheus + cAdvisor accessible from the central server. This means:
- Firewall rules allowing Prometheus's port (9090) between servers
- Either public IPs or a private network between machines
- Running Prometheus on every server (resource cost, maintenance)
- Managing certificates or VPNs if servers are across different providers
This works well in a controlled environment (AWS VPC, private network) but is painful for a mix of VPS providers.
Option 2: Netdata (easy per-host, multi-host via their cloud)
Netdata is a lightweight monitoring agent that runs on each host and exposes a beautiful per-host dashboard. Their cloud product connects multiple Netdata instances into a single view.
Setup per host:
wget -O /tmp/netdata-kickstart.sh https://get.netdata.cloud/kickstart.sh
sh /tmp/netdata-kickstart.sh
Pros:
- Very easy to install (one command per host)
- Beautiful, high-resolution (per-second) dashboards
- Docker container monitoring built-in
- Cloud product gives you multi-host view
Cons:
- Free cloud tier has limitations on retention and features
- Paid plans start at $5-10+/host/month for full features
- No alert for Discord, Telegram out of the box
- No status page or uptime badges
Good option if you want detailed per-second metrics and are comfortable with their pricing.
Option 3: Beszel (self-hosted, free)
Beszel is a self-hosted multi-host monitoring tool that's getting traction in the homelab and indie hacker community. You run a central Beszel hub and lightweight agents on each server.
Setup:
# On the monitoring server (beszel-hub):
services:
beszel:
image: henrygd/beszel
ports:
- "8090:8090"
volumes:
- ./beszel_data:/beszel_data
# On each monitored server (beszel-agent):
services:
beszel-agent:
image: henrygd/beszel-agent
environment:
- KEY=your_public_key_from_hub
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
Pros:
- Free forever (self-hosted)
- Clean, simple UI
- Multi-host out of the box
- No external dependencies
Cons:
- You're responsible for the hub's availability (if it goes down, monitoring goes down)
- Limited alerting channels
- No status pages or uptime badges
- Requires a VPS or server to host the hub
- You own the maintenance
Great for homelabs and side projects where budget is zero. Less appropriate when production uptime matters and you need your monitoring system to be more reliable than the things it monitors.
Option 4: Kernus (hosted, multi-host with one dashboard)
Kernus was designed for the multi-host use case from day one. You install the agent on each server independently — each gets its own agent token. All hosts report to the same organization dashboard.
Adding your first host
# On server 1:
curl -fsSL https://kernus.app/install | sh
kernus token TOKEN_FOR_HOST_1 --host company-backend-1
kernus agent start
Windows: Use WSL or Git Bash for this one-liner, or use PowerShell (see Windows install).
Adding a second host
In Kernus dashboard → Settings → Agent Tokens → Create Token. Label it with the hostname or location. Then on server 2:
# On server 2:
curl -fsSL https://kernus.app/install | sh
kernus token TOKEN_FOR_HOST_2 --host company-backend-2
kernus agent start
Windows: Use WSL or Git Bash for this one-liner, or use PowerShell (see Windows install).
Both hosts appear in your dashboard within seconds. No network configuration between servers. No firewall rules. Each agent only needs outbound HTTPS to api.kernus.app.
What multi-host monitoring looks like in Kernus
- Nodes overview — all servers in one grid, color-coded by health status
- Cross-host alerts — alert rules apply across all hosts by default
- Container browser — filter by host, or see all containers across all hosts
- Unified incident history — all container events across all hosts in one feed
- Status page — shows per-node and per-container health across your entire fleet
Scaling across multiple hosts: the agent token model
Kernus uses one agent token per host. Each token is stored hashed (SHA-256) and displayed only once at creation. You can:
- Label tokens descriptively (
prod-web-server,prod-worker-eu,staging-db) - Revoke individual tokens without affecting other hosts
- See which token last reported and when (useful for detecting dead agents)
Plan limits apply to the total number of hosts per organization:
- Free: 1 host (up to 6 containers)
- Pro: 5 hosts (up to 30 containers)
- Business: 30 hosts (up to 150 containers)
- Enterprise: Unlimited
The network model: why push-based beats pull-based for multi-host
When you have servers across multiple data centers, cloud providers, or geographic regions, a pull-based system (like Prometheus) requires that your monitoring server can reach each monitored server's metrics port. This often means:
- Opening firewall ports
- Public IPs or a VPN/mesh network
- Dealing with different network topologies per cloud provider
A push-based system (like Kernus) inverts this. Each agent reaches out to the central server. The requirements are simple: each server needs outbound HTTPS (port 443). This works everywhere — behind corporate firewalls, on home networks, in any cloud provider, even on servers you don't control the firewall for.
This is why push-based monitoring is the default choice for SaaS monitoring tools and why most teams end up choosing it when they expand beyond a single managed network.
Comparing multi-host options
| Tool | Multi-host | Setup effort | Alerting | Status page | Monthly cost |
|---|---|---|---|---|---|
| Prometheus + federation | ✅ | Very high | Via Alertmanager | ❌ | $0 (self-hosted) |
| Netdata Cloud | ✅ | Low | Basic | ❌ | $5-10+/host |
| Beszel | ✅ | Medium | Basic | ❌ | $0 (self-hosted VPS cost) |
| Kernus | ✅ | 2 min/host | Full (6 channels) | ✅ Pro+ (shareable page) | $29-99/mo flat |
| Datadog | ✅ | Medium | Extensive | ❌ (separate product) | $23+/host/mo |
Running kernus agent as a systemd service (production setup)
For production, you don't want the agent to stop when you log out. Run it as a systemd service:
# Create the service file
sudo tee /etc/systemd/system/kernus-agent.service > /dev/null << 'EOF'
[Unit]
Description=Kernus Monitoring Agent
After=docker.service
Requires=docker.service
[Service]
Type=simple
User=root
Environment=KERNUS_AGENT_TOKEN=your_token_here
Environment=KERNUS_HOST_NAME=prod-server-1
ExecStart=/usr/local/bin/kernus agent start
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable kernus-agent
sudo systemctl start kernus-agent
Verify it's running:
sudo systemctl status kernus-agent
The agent will now automatically start on boot and restart if it crashes.
For the complete monitoring setup guide: Docker container monitoring — complete guide 2025. For keeping costs down: Docker monitoring on a budget.
Try Kernus free
Set up Docker monitoring in 2 minutes. Free for 1 host — no credit card required.
Start monitoring