├── README.md ├── dashboard.json ├── datasources.yml ├── default.yaml ├── docker-compose.yml └── prometheus.yml /README.md: -------------------------------------------------------------------------------- 1 | # Docker Container Monitoring with cAdvisor, Prometheus, and Grafana using Docker Compose 2 | Command to run docker-compose.yml 3 | ```bash 4 | $ docker compose up 5 | ``` 6 | You can access cAdvisor on http://localhost:8080, Prometheus on http://localhost:9090, and Grafana on http://localhost:3000. 7 | -------------------------------------------------------------------------------- /dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": { 3 | "list": [ 4 | { 5 | "builtIn": 1, 6 | "datasource": { 7 | "type": "grafana", 8 | "uid": "-- Grafana --" 9 | }, 10 | "enable": true, 11 | "hide": true, 12 | "iconColor": "rgba(0, 211, 255, 1)", 13 | "name": "Annotations & Alerts", 14 | "type": "dashboard" 15 | } 16 | ] 17 | }, 18 | "description": "Docker monitoring with Prometheus and cAdvisor", 19 | "editable": true, 20 | "fiscalYearStartMonth": 0, 21 | "gnetId": 193, 22 | "graphTooltip": 1, 23 | "id": 3, 24 | "links": [], 25 | "liveNow": false, 26 | "panels": [ 27 | { 28 | "datasource": { 29 | "type": "prometheus", 30 | "uid": "prometheus" 31 | }, 32 | "fieldConfig": { 33 | "defaults": { 34 | "color": { 35 | "mode": "thresholds" 36 | }, 37 | "mappings": [ 38 | { 39 | "options": { 40 | "match": "null", 41 | "result": { 42 | "text": "N/A" 43 | } 44 | }, 45 | "type": "special" 46 | } 47 | ], 48 | "thresholds": { 49 | "mode": "absolute", 50 | "steps": [ 51 | { 52 | "color": "green", 53 | "value": null 54 | }, 55 | { 56 | "color": "red", 57 | "value": 80 58 | } 59 | ] 60 | }, 61 | "unit": "none" 62 | }, 63 | "overrides": [] 64 | }, 65 | "gridPos": { 66 | "h": 3, 67 | "w": 8, 68 | "x": 0, 69 | "y": 0 70 | }, 71 | "id": 7, 72 | "links": [], 73 | "maxDataPoints": 100, 74 | "options": { 75 | "colorMode": "none", 76 | "graphMode": "none", 77 | "justifyMode": "auto", 78 | "orientation": "horizontal", 79 | "reduceOptions": { 80 | "calcs": [ 81 | "mean" 82 | ], 83 | "fields": "", 84 | "values": false 85 | }, 86 | "textMode": "auto" 87 | }, 88 | "pluginVersion": "10.0.2", 89 | "targets": [ 90 | { 91 | "datasource": { 92 | "type": "prometheus", 93 | "uid": "prometheus" 94 | }, 95 | "expr": "count(container_last_seen{image!=\"\"})", 96 | "intervalFactor": 2, 97 | "legendFormat": "", 98 | "metric": "container_last_seen", 99 | "refId": "A", 100 | "step": 240 101 | } 102 | ], 103 | "title": "Running containers", 104 | "transparent": true, 105 | "type": "stat" 106 | }, 107 | { 108 | "datasource": { 109 | "type": "prometheus", 110 | "uid": "prometheus" 111 | }, 112 | "fieldConfig": { 113 | "defaults": { 114 | "color": { 115 | "mode": "thresholds" 116 | }, 117 | "mappings": [ 118 | { 119 | "options": { 120 | "match": "null", 121 | "result": { 122 | "text": "N/A" 123 | } 124 | }, 125 | "type": "special" 126 | } 127 | ], 128 | "thresholds": { 129 | "mode": "absolute", 130 | "steps": [ 131 | { 132 | "color": "green", 133 | "value": null 134 | }, 135 | { 136 | "color": "red", 137 | "value": 80 138 | } 139 | ] 140 | }, 141 | "unit": "mbytes" 142 | }, 143 | "overrides": [] 144 | }, 145 | "gridPos": { 146 | "h": 3, 147 | "w": 8, 148 | "x": 8, 149 | "y": 0 150 | }, 151 | "id": 5, 152 | "links": [], 153 | "maxDataPoints": 100, 154 | "options": { 155 | "colorMode": "none", 156 | "graphMode": "none", 157 | "justifyMode": "auto", 158 | "orientation": "horizontal", 159 | "reduceOptions": { 160 | "calcs": [ 161 | "lastNotNull" 162 | ], 163 | "fields": "", 164 | "values": false 165 | }, 166 | "textMode": "auto" 167 | }, 168 | "pluginVersion": "10.0.2", 169 | "targets": [ 170 | { 171 | "datasource": { 172 | "type": "prometheus", 173 | "uid": "prometheus" 174 | }, 175 | "expr": "sum(container_memory_usage_bytes{image!=\"\"})/1024/1024", 176 | "intervalFactor": 2, 177 | "legendFormat": "", 178 | "metric": "container_memory_usage_bytes", 179 | "refId": "A", 180 | "step": 240 181 | } 182 | ], 183 | "title": "Total Memory Usage", 184 | "transparent": true, 185 | "type": "stat" 186 | }, 187 | { 188 | "datasource": { 189 | "type": "prometheus", 190 | "uid": "prometheus" 191 | }, 192 | "fieldConfig": { 193 | "defaults": { 194 | "color": { 195 | "mode": "thresholds" 196 | }, 197 | "mappings": [ 198 | { 199 | "options": { 200 | "match": "null", 201 | "result": { 202 | "text": "N/A" 203 | } 204 | }, 205 | "type": "special" 206 | } 207 | ], 208 | "thresholds": { 209 | "mode": "absolute", 210 | "steps": [ 211 | { 212 | "color": "green", 213 | "value": null 214 | }, 215 | { 216 | "color": "red", 217 | "value": 80 218 | } 219 | ] 220 | }, 221 | "unit": "percent" 222 | }, 223 | "overrides": [] 224 | }, 225 | "gridPos": { 226 | "h": 3, 227 | "w": 8, 228 | "x": 16, 229 | "y": 0 230 | }, 231 | "id": 6, 232 | "links": [], 233 | "maxDataPoints": 100, 234 | "options": { 235 | "colorMode": "none", 236 | "graphMode": "none", 237 | "justifyMode": "auto", 238 | "orientation": "horizontal", 239 | "reduceOptions": { 240 | "calcs": [ 241 | "lastNotNull" 242 | ], 243 | "fields": "", 244 | "values": false 245 | }, 246 | "textMode": "auto" 247 | }, 248 | "pluginVersion": "10.0.2", 249 | "targets": [ 250 | { 251 | "datasource": { 252 | "type": "prometheus", 253 | "uid": "prometheus" 254 | }, 255 | "expr": "sum(rate(container_cpu_user_seconds_total{image!=\"\"}[5m]) * 100)", 256 | "intervalFactor": 2, 257 | "legendFormat": "", 258 | "metric": "container_memory_usage_bytes", 259 | "refId": "A", 260 | "step": 240 261 | } 262 | ], 263 | "title": "Total CPU Usage", 264 | "transparent": true, 265 | "type": "stat" 266 | }, 267 | { 268 | "aliasColors": {}, 269 | "bars": false, 270 | "dashLength": 10, 271 | "dashes": false, 272 | "datasource": { 273 | "type": "prometheus", 274 | "uid": "prometheus" 275 | }, 276 | "decimals": 2, 277 | "editable": true, 278 | "error": false, 279 | "fill": 1, 280 | "fillGradient": 0, 281 | "grid": {}, 282 | "gridPos": { 283 | "h": 7, 284 | "w": 24, 285 | "x": 0, 286 | "y": 3 287 | }, 288 | "hiddenSeries": false, 289 | "id": 2, 290 | "legend": { 291 | "alignAsTable": true, 292 | "avg": true, 293 | "current": true, 294 | "max": false, 295 | "min": false, 296 | "rightSide": true, 297 | "show": true, 298 | "total": false, 299 | "values": true 300 | }, 301 | "lines": true, 302 | "linewidth": 2, 303 | "links": [], 304 | "nullPointMode": "connected", 305 | "options": { 306 | "alertThreshold": true 307 | }, 308 | "percentage": false, 309 | "pluginVersion": "10.0.2", 310 | "pointradius": 5, 311 | "points": false, 312 | "renderer": "flot", 313 | "seriesOverrides": [], 314 | "spaceLength": 10, 315 | "stack": false, 316 | "steppedLine": false, 317 | "targets": [ 318 | { 319 | "datasource": { 320 | "type": "prometheus", 321 | "uid": "prometheus" 322 | }, 323 | "expr": "rate(container_cpu_user_seconds_total{image!=\"\"}[5m]) * 100", 324 | "intervalFactor": 2, 325 | "legendFormat": "{{name}}", 326 | "metric": "cpu", 327 | "refId": "A", 328 | "step": 10 329 | } 330 | ], 331 | "thresholds": [], 332 | "timeRegions": [], 333 | "title": "CPU Usage", 334 | "tooltip": { 335 | "msResolution": false, 336 | "shared": true, 337 | "sort": 0, 338 | "value_type": "cumulative" 339 | }, 340 | "type": "graph", 341 | "xaxis": { 342 | "mode": "time", 343 | "show": true, 344 | "values": [] 345 | }, 346 | "yaxes": [ 347 | { 348 | "format": "percent", 349 | "logBase": 1, 350 | "show": true 351 | }, 352 | { 353 | "format": "short", 354 | "logBase": 1, 355 | "show": true 356 | } 357 | ], 358 | "yaxis": { 359 | "align": false 360 | } 361 | }, 362 | { 363 | "aliasColors": {}, 364 | "bars": false, 365 | "dashLength": 10, 366 | "dashes": false, 367 | "datasource": { 368 | "type": "prometheus", 369 | "uid": "prometheus" 370 | }, 371 | "decimals": 2, 372 | "editable": true, 373 | "error": false, 374 | "fill": 1, 375 | "fillGradient": 0, 376 | "grid": {}, 377 | "gridPos": { 378 | "h": 7, 379 | "w": 24, 380 | "x": 0, 381 | "y": 10 382 | }, 383 | "hiddenSeries": false, 384 | "id": 1, 385 | "legend": { 386 | "alignAsTable": true, 387 | "avg": true, 388 | "current": true, 389 | "max": false, 390 | "min": false, 391 | "rightSide": true, 392 | "show": true, 393 | "total": false, 394 | "values": true 395 | }, 396 | "lines": true, 397 | "linewidth": 2, 398 | "links": [], 399 | "nullPointMode": "connected", 400 | "options": { 401 | "alertThreshold": true 402 | }, 403 | "percentage": false, 404 | "pluginVersion": "10.0.2", 405 | "pointradius": 5, 406 | "points": false, 407 | "renderer": "flot", 408 | "seriesOverrides": [], 409 | "spaceLength": 10, 410 | "stack": false, 411 | "steppedLine": false, 412 | "targets": [ 413 | { 414 | "datasource": { 415 | "type": "prometheus", 416 | "uid": "prometheus" 417 | }, 418 | "expr": "container_memory_usage_bytes{image!=\"\"}", 419 | "hide": false, 420 | "intervalFactor": 2, 421 | "legendFormat": "{{name}}", 422 | "metric": "container_memory_usage_bytes", 423 | "refId": "A", 424 | "step": 10 425 | } 426 | ], 427 | "thresholds": [], 428 | "timeRegions": [], 429 | "title": "Memory Usage", 430 | "tooltip": { 431 | "msResolution": false, 432 | "shared": true, 433 | "sort": 0, 434 | "value_type": "cumulative" 435 | }, 436 | "type": "graph", 437 | "xaxis": { 438 | "mode": "time", 439 | "show": true, 440 | "values": [] 441 | }, 442 | "yaxes": [ 443 | { 444 | "format": "bytes", 445 | "label": "", 446 | "logBase": 1, 447 | "show": true 448 | }, 449 | { 450 | "format": "short", 451 | "logBase": 1, 452 | "show": false 453 | } 454 | ], 455 | "yaxis": { 456 | "align": false 457 | } 458 | }, 459 | { 460 | "aliasColors": {}, 461 | "bars": false, 462 | "dashLength": 10, 463 | "dashes": false, 464 | "datasource": { 465 | "type": "prometheus", 466 | "uid": "prometheus" 467 | }, 468 | "editable": true, 469 | "error": false, 470 | "fill": 1, 471 | "fillGradient": 0, 472 | "grid": {}, 473 | "gridPos": { 474 | "h": 7, 475 | "w": 12, 476 | "x": 0, 477 | "y": 17 478 | }, 479 | "hiddenSeries": false, 480 | "id": 3, 481 | "legend": { 482 | "avg": false, 483 | "current": false, 484 | "max": false, 485 | "min": false, 486 | "show": true, 487 | "total": false, 488 | "values": false 489 | }, 490 | "lines": true, 491 | "linewidth": 2, 492 | "links": [], 493 | "nullPointMode": "connected", 494 | "options": { 495 | "alertThreshold": true 496 | }, 497 | "percentage": false, 498 | "pluginVersion": "10.0.2", 499 | "pointradius": 5, 500 | "points": false, 501 | "renderer": "flot", 502 | "seriesOverrides": [], 503 | "spaceLength": 10, 504 | "stack": false, 505 | "steppedLine": false, 506 | "targets": [ 507 | { 508 | "datasource": { 509 | "type": "prometheus", 510 | "uid": "prometheus" 511 | }, 512 | "expr": "irate(container_network_receive_bytes_total{image!=\"\"}[5m])", 513 | "intervalFactor": 2, 514 | "legendFormat": "{{name}}", 515 | "metric": "container_network_receive_bytes_total", 516 | "refId": "A", 517 | "step": 20 518 | } 519 | ], 520 | "thresholds": [], 521 | "timeRegions": [], 522 | "title": "Network Rx", 523 | "tooltip": { 524 | "msResolution": false, 525 | "shared": true, 526 | "sort": 0, 527 | "value_type": "cumulative" 528 | }, 529 | "type": "graph", 530 | "xaxis": { 531 | "mode": "time", 532 | "show": true, 533 | "values": [] 534 | }, 535 | "yaxes": [ 536 | { 537 | "format": "Bps", 538 | "logBase": 1, 539 | "show": true 540 | }, 541 | { 542 | "format": "short", 543 | "logBase": 1, 544 | "show": true 545 | } 546 | ], 547 | "yaxis": { 548 | "align": false 549 | } 550 | }, 551 | { 552 | "aliasColors": {}, 553 | "bars": false, 554 | "dashLength": 10, 555 | "dashes": false, 556 | "datasource": { 557 | "type": "prometheus", 558 | "uid": "prometheus" 559 | }, 560 | "editable": true, 561 | "error": false, 562 | "fill": 1, 563 | "fillGradient": 0, 564 | "grid": {}, 565 | "gridPos": { 566 | "h": 7, 567 | "w": 12, 568 | "x": 12, 569 | "y": 17 570 | }, 571 | "hiddenSeries": false, 572 | "id": 4, 573 | "legend": { 574 | "avg": false, 575 | "current": false, 576 | "max": false, 577 | "min": false, 578 | "show": true, 579 | "total": false, 580 | "values": false 581 | }, 582 | "lines": true, 583 | "linewidth": 2, 584 | "links": [], 585 | "nullPointMode": "connected", 586 | "options": { 587 | "alertThreshold": true 588 | }, 589 | "percentage": false, 590 | "pluginVersion": "10.0.2", 591 | "pointradius": 5, 592 | "points": false, 593 | "renderer": "flot", 594 | "seriesOverrides": [], 595 | "spaceLength": 10, 596 | "stack": false, 597 | "steppedLine": false, 598 | "targets": [ 599 | { 600 | "datasource": { 601 | "type": "prometheus", 602 | "uid": "prometheus" 603 | }, 604 | "expr": "irate(container_network_transmit_bytes_total{image!=\"\"}[5m])", 605 | "intervalFactor": 2, 606 | "legendFormat": "{{name}}", 607 | "refId": "A", 608 | "step": 20 609 | } 610 | ], 611 | "thresholds": [], 612 | "timeRegions": [], 613 | "title": "Network Tx", 614 | "tooltip": { 615 | "msResolution": false, 616 | "shared": true, 617 | "sort": 0, 618 | "value_type": "cumulative" 619 | }, 620 | "type": "graph", 621 | "xaxis": { 622 | "mode": "time", 623 | "show": true, 624 | "values": [] 625 | }, 626 | "yaxes": [ 627 | { 628 | "format": "Bps", 629 | "logBase": 1, 630 | "show": true 631 | }, 632 | { 633 | "format": "short", 634 | "logBase": 1, 635 | "show": true 636 | } 637 | ], 638 | "yaxis": { 639 | "align": false 640 | } 641 | } 642 | ], 643 | "refresh": "10s", 644 | "schemaVersion": 38, 645 | "style": "dark", 646 | "tags": [ 647 | "docker" 648 | ], 649 | "templating": { 650 | "list": [] 651 | }, 652 | "time": { 653 | "from": "now-5m", 654 | "to": "now" 655 | }, 656 | "timepicker": { 657 | "refresh_intervals": [ 658 | "5s", 659 | "10s", 660 | "30s", 661 | "1m", 662 | "5m", 663 | "15m", 664 | "30m", 665 | "1h", 666 | "2h", 667 | "1d" 668 | ], 669 | "time_options": [ 670 | "5m", 671 | "15m", 672 | "1h", 673 | "6h", 674 | "12h", 675 | "24h", 676 | "2d", 677 | "7d", 678 | "30d" 679 | ] 680 | }, 681 | "timezone": "browser", 682 | "title": "Docker Monitoring Test", 683 | "uid": "ee75b6b8-f1c6-4ef1-9d39-fe50cc55a274", 684 | "version": 1, 685 | "weekStart": "" 686 | } -------------------------------------------------------------------------------- /datasources.yml: -------------------------------------------------------------------------------- 1 | datasources: 2 | - name: prometheus 3 | type: prometheus 4 | url: http://localhost:9090 5 | access: proxy 6 | isDefault: true 7 | -------------------------------------------------------------------------------- /default.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | providers: 4 | - name: Default # A uniquely identifiable name for the provider 5 | folder: Services # The folder where to place the dashboards 6 | type: file 7 | options: 8 | path: /var/lib/grafana/dashboards/dashboard.json -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | cadvisor: 4 | container_name: cadvisor 5 | image: gcr.io/cadvisor/cadvisor:latest 6 | network_mode: "host" 7 | ports: 8 | - "8080:8080" 9 | volumes: 10 | - "/:/rootfs" 11 | - "/var/run:/var/run" 12 | - "/sys:/sys" 13 | - "/var/lib/docker/:/var/lib/docker" 14 | - "/dev/disk/:/dev/disk" 15 | privileged: true 16 | devices: 17 | - "/dev/kmsg" 18 | 19 | prometheus: 20 | container_name: prometheus 21 | image: prom/prometheus:latest 22 | network_mode: "host" 23 | ports: 24 | - "9090:9090" 25 | volumes: 26 | - "./prometheus.yml:/etc/prometheus/prometheus.yml" 27 | privileged: true 28 | depends_on: 29 | - cadvisor 30 | 31 | grafana: 32 | container_name: grafana 33 | image: grafana/grafana:latest 34 | network_mode: "host" 35 | ports: 36 | - "3000:3000" 37 | environment: 38 | - GF_PATHS_PROVISIONING=/etc/grafana/provisioning 39 | - DS_PROMETHEUS=prometheus 40 | volumes: 41 | - "grafana-data:/var/lib/grafana" 42 | - "./datasources.yml:/etc/grafana/provisioning/datasources/datasources.yml" 43 | - "./dashboard.json:/var/lib/grafana/dashboards/dashboard.json" 44 | - "./default.yaml:/etc/grafana/provisioning/dashboards/default.yaml" 45 | privileged: true 46 | depends_on: 47 | - prometheus 48 | 49 | volumes: 50 | grafana-data: -------------------------------------------------------------------------------- /prometheus.yml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 15s #Scrape interval to every 15 seconds. 3 | evaluation_interval: 15s #Evaluate rules every 15 seconds. 4 | 5 | scrape_configs: 6 | - job_name: "prometheus" 7 | # metrics_path defaults to '/metrics' 8 | static_configs: 9 | - targets: ["localhost:9090"] 10 | 11 | - job_name: "cadvisor" 12 | static_configs: 13 | - targets: ["localhost:8080"] 14 | --------------------------------------------------------------------------------