The Complete Docker Monitoring Guide 2026
Docker containers fail in ways that traditional monitoring was never built to catch. A container can appear healthy from Docker's perspective — Status: Up — while silently refusing all external traffic. A Docker Compose application can have half its services crash-looping while the other half report healthy. A health check can pass the local curl test every 30 seconds while a misconfigured nginx rule serves 502s to every real user.
This guide is a complete reference for monitoring Dockerized applications in 2026. It covers container-native health mechanisms, what docker stats and logs can and cannot tell you, and how Vigilmon closes the monitoring gap with external uptime visibility.
Why Docker Monitoring Is Harder Than It Looks
The appeal of Docker is isolation and reproducibility. The liability is the same: the container is opaque. From the host perspective, you know:
- Whether the container process is running
- Whether the container's health check (if defined) passes
- Resource utilization: CPU, memory, network I/O
- Log output (if you're collecting it)
What you do not know from the container layer:
- Whether external clients can actually reach the exposed service
- Whether the application is handling requests successfully or returning errors
- Whether response times are within acceptable thresholds
- Whether SSL certificates are valid and not about to expire
- Whether a port mapping silently failed on container start
These gaps are not hypothetical. They are the failure modes that produce the most embarrassing outages — the kind where Slack lights up with customer complaints before anyone on the team notices.
Docker's Built-In Health Mechanisms
Container Status
docker ps reports each container's status: Up, Exited, Restarting, or Created. Restarting is the silent killer — a container in a restart loop shows as Restarting transiently, but between restarts briefly shows as Up. If your monitoring just checks for Up, it will miss crash loops.
Better approach: Monitor restart counts. docker inspect --format '{{.RestartCount}}' <container> reveals how many times a container has restarted since it was created. A monotonically increasing restart count is a crash loop regardless of current status.
HEALTHCHECK Instruction
Docker supports a HEALTHCHECK instruction that runs a command inside the container on a schedule. A container is healthy, unhealthy, or starting.
FROM node:20-alpine
WORKDIR /app
COPY . .
RUN npm ci --production
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
CMD ["node", "server.js"]
What HEALTHCHECK catches: Process-level failures visible from within the container — the app stopped listening on port 3000, the health endpoint returns non-2xx, the response takes more than 5 seconds.
What HEALTHCHECK misses: External failures. The HEALTHCHECK runs inside the container network namespace. It never traverses the host's port mapping, the bridge network, or any upstream proxy. A health check can pass while external clients see connection refused.
Docker Compose Health Dependencies
Docker Compose supports condition: service_healthy in depends_on, preventing dependent containers from starting until their dependencies pass their HEALTHCHECK:
services:
db:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
api:
image: myapp:latest
depends_on:
db:
condition: service_healthy
ports:
- "8080:8080"
This prevents the classic "app started before database was ready" race condition. Use it for every service that has a downstream dependency.
What docker stats Tells You
docker stats streams live resource utilization for all running containers:
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O
a3f8b1c2d4e5 api 2.3% 128MiB / 1GiB 12.5% 4.2MB / 1.1MB 0B / 0B
Useful for: Detecting memory leaks (MEM USAGE grows monotonically), CPU spikes correlated with load, network I/O anomalies.
Not useful for: Application correctness, response times, error rates, external reachability, SSL status. docker stats is a resource meter, not an application health tool.
What Docker Logs Tell You
Log aggregation — shipping container logs to Loki, Elasticsearch, CloudWatch, or Papertrail — is essential for debugging. Logs tell you what happened after the fact. They are not a monitoring system.
Log-based monitoring has structural problems:
- Volume: A busy service logs thousands of lines per minute. Manual inspection is impossible; automated log parsing is brittle.
- No external perspective: Logs only show what the application decided to log. A connection refused at the port mapping level produces no application log.
- Latency: Log-based alerts typically have 30–120 second lag from error to alert, depending on pipeline architecture.
Use logs for debugging. Use uptime monitoring for alerting.
The Monitoring Gap: What External Visibility Adds
External uptime monitoring — a service outside your Docker environment probing your public endpoints — covers the failure modes that container-native tools cannot:
| Failure Mode | docker stats/logs/HEALTHCHECK | Vigilmon (external) | |---|---|---| | Port mapping silently failed | No | Yes | | Host firewall blocking traffic | No | Yes | | Reverse proxy (nginx) misconfigured | No | Yes | | SSL certificate expired | No | Yes | | DNS record pointing to wrong IP | No | Yes | | Response time degraded (external) | No | Yes | | Service returns 500 errors | Log only | Yes (with content matching) | | Container crash loop | Partial | Yes (endpoint unreachable) |
Vigilmon probes your public endpoints from multiple geographic locations every minute. It requires 3+ independent monitoring nodes to agree before triggering an alert, eliminating false positives from transient regional issues.
Practical Monitoring Setup for Docker Applications
Step 1: Implement a Real Health Endpoint
Your application should expose a /health endpoint that checks actual dependencies, not just that the process is running:
// Node.js + Express example
app.get('/health', async (req, res) => {
try {
await db.query('SELECT 1'); // verify DB connectivity
await redis.ping(); // verify cache connectivity
res.json({ status: 'ok', timestamp: new Date().toISOString() });
} catch (err) {
res.status(503).json({ status: 'error', detail: err.message });
}
});
A health endpoint that just returns 200 OK unconditionally tells you nothing. A health endpoint that checks real dependencies is the foundation of both your Docker HEALTHCHECK and your Vigilmon monitor.
Step 2: Configure Docker HEALTHCHECK
Reference your health endpoint in the Dockerfile:
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
CMD curl -f http://localhost:8080/health || exit 1
For Docker Compose, override or supplement the Dockerfile HEALTHCHECK:
services:
api:
image: myapp:latest
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
start_period: 30s
retries: 3
Step 3: Export Container Metrics
For resource monitoring, add Prometheus exporters to your Compose stack:
services:
cadvisor:
image: gcr.io/cadvisor/cadvisor:v0.47.2
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
ports:
- "8081:8080"
cAdvisor exposes per-container CPU, memory, and network metrics that Prometheus can scrape.
Step 4: Set Up External Monitoring with Vigilmon
This is the critical step that most Docker tutorials skip.
- Sign up at vigilmon.online — free tier, no credit card.
- Add HTTP monitors for each public-facing endpoint:
- Your application's root URL
- Your
/healthendpoint - Any API endpoints that external systems call
- Configure response validation: Set the expected HTTP status code (200) and optionally a string that should appear in the response body.
- Set response time thresholds: Alert when response time exceeds 2 seconds — catching degradation before it becomes an outage.
- Enable SSL monitoring: Vigilmon checks your certificate expiry and alerts at 14 and 7 days before expiry.
Step 5: Monitor Docker Compose at the Compose Level
For applications with multiple services, expose a compose-level health endpoint that aggregates the health of all services:
# Python/Flask example: aggregate health endpoint
@app.route('/health/all')
def health_all():
checks = {
'db': check_db(),
'cache': check_redis(),
'queue': check_rabbitmq(),
}
status = 'ok' if all(v == 'ok' for v in checks.values()) else 'degraded'
code = 200 if status == 'ok' else 503
return jsonify({'status': status, 'services': checks}), code
Monitor this aggregate endpoint in Vigilmon so a single alert covers the entire application stack.
Alert Routing and Incident Response
Alerting Configuration in Vigilmon
Configure alert channels appropriate for your team size:
Solo developers and small teams:
- Email alerts with a 2-minute confirmation delay (avoids alerts for brief blips)
- Slack webhook to your
#alertschannel
Larger teams with on-call rotations:
- Webhook integration to PagerDuty or OpsGenie for escalating alerts
- Slack for informational notifications
- Email as backup
Vigilmon's consensus alerting (3+ global nodes must agree before alerting) means that by the time an alert fires, the issue is real and warrants action. You will not be woken at 3am for a 30-second regional network hiccup.
Setting Alert Thresholds
For production Docker services:
- Check interval: 1 minute (Vigilmon free tier default)
- Response time alert: 2 seconds (warn), 5 seconds (critical)
- SSL expiry alert: 14 days before expiry
- Confirmation delay: 2 minutes (Vigilmon checks 3 times before alerting)
Docker Monitoring Checklist for 2026
Container Health
- [ ] HEALTHCHECK defined in Dockerfile or docker-compose.yml
- [ ] Health endpoint checks real dependencies (DB, cache, queues)
- [ ] Restart count monitoring (crash loop detection)
- [ ]
depends_on: condition: service_healthyfor dependent services
Resource Monitoring
- [ ] cAdvisor or similar for per-container CPU/memory metrics
- [ ] Memory limit set on each container (
--memoryormem_limit) - [ ] Log aggregation pipeline (Loki, CloudWatch, Papertrail)
External Uptime (Vigilmon)
- [ ] HTTP monitor for every public endpoint
- [ ] SSL certificate expiry monitoring
- [ ] Response time threshold alerts
- [ ] Multi-region availability (3+ node consensus)
- [ ] Alert routing to Slack/PagerDuty
Summary
Effective Docker monitoring in 2026 requires two complementary perspectives. From inside the container: HEALTHCHECK instructions, dependency health validation, and resource metrics via cAdvisor. From outside: Vigilmon's external uptime monitoring, which catches the failure modes that container-native tools cannot see.
The combination closes the full loop. When docker ps shows all containers healthy and users are still reporting errors, Vigilmon tells you whether the nginx proxy is misconfigured, the host firewall is blocking traffic, or the SSL certificate expired at 3am.
Add external visibility to your Docker stack today — try Vigilmon free, no credit card required.