├── .github ├── dependabot.yml └── workflows │ ├── grafana.yml │ ├── prometheus.yml │ └── substrate.yml ├── README.md ├── grafana ├── Dockerfile ├── dashboard.json └── entrypoint.sh ├── monk ├── README.md ├── core │ ├── grafana.yml │ ├── prometheus.yml │ └── substrate.yml ├── examples │ └── lb_nodes.yml └── hub │ ├── rococo │ └── substrate.yml │ └── stack.yml ├── prometheus ├── Dockerfile ├── config.yml └── entrypoint.sh └── substrate └── Dockerfile /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | - package-ecosystem: "docker" 8 | directory: "/" 9 | schedule: 10 | interval: "daily" 11 | -------------------------------------------------------------------------------- /.github/workflows/grafana.yml: -------------------------------------------------------------------------------- 1 | name: Grafana 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | schedule: 8 | - cron: '0 10 * * *' # everyday at 10am 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - 15 | name: Checkout 16 | uses: actions/checkout@v3.3.0 17 | - 18 | name: Set up Docker Buildx 19 | uses: docker/setup-buildx-action@v2.4.0 20 | - 21 | name: Login to DockerHub 22 | if: github.event_name != 'pull_request' 23 | uses: docker/login-action@v1.10.0 24 | with: 25 | username: ${{ secrets.DOCKERHUB_USERNAME }} 26 | password: ${{ secrets.DOCKERHUB_TOKEN }} 27 | - 28 | name: Build and push 29 | uses: docker/build-push-action@v4.0.0 30 | with: 31 | context: ./grafana 32 | file: ./grafana/Dockerfile 33 | push: ${{ github.event_name != 'pull_request' }} 34 | cache-from: type=local,src=/tmp/.buildx-cache 35 | cache-to: type=local,dest=/tmp/.buildx-cache 36 | tags: eteissonniere/substrate-grafana:latest 37 | -------------------------------------------------------------------------------- /.github/workflows/prometheus.yml: -------------------------------------------------------------------------------- 1 | name: Prometheus 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | schedule: 8 | - cron: '0 10 * * *' # everyday at 10am 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - 15 | name: Checkout 16 | uses: actions/checkout@v3.3.0 17 | - 18 | name: Set up Docker Buildx 19 | uses: docker/setup-buildx-action@v2.4.0 20 | - 21 | name: Login to DockerHub 22 | if: github.event_name != 'pull_request' 23 | uses: docker/login-action@v1.10.0 24 | with: 25 | username: ${{ secrets.DOCKERHUB_USERNAME }} 26 | password: ${{ secrets.DOCKERHUB_TOKEN }} 27 | - 28 | name: Build and push 29 | uses: docker/build-push-action@v4.0.0 30 | with: 31 | context: ./prometheus 32 | file: ./prometheus/Dockerfile 33 | push: ${{ github.event_name != 'pull_request' }} 34 | cache-from: type=local,src=/tmp/.buildx-cache 35 | cache-to: type=local,dest=/tmp/.buildx-cache 36 | tags: eteissonniere/substrate-prometheus:latest 37 | -------------------------------------------------------------------------------- /.github/workflows/substrate.yml: -------------------------------------------------------------------------------- 1 | name: Nodes 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | schedule: 8 | - cron: '0 10 * * *' # everyday at 10am 9 | 10 | jobs: 11 | build: 12 | continue-on-error: true 13 | strategy: 14 | matrix: 15 | include: 16 | # Add your own details here, just duplicate one of the entries below. 17 | # `binary` is the name of your binary as created by cargo 18 | # `branch` is the git branch to fetch 19 | # `git` is your github repo URL (must be publicly accessible) 20 | # `package` is the rust package to build that will produce your binary 21 | # `name` is the name of the docker container to push 22 | 23 | - 24 | binary: nodle-parachain 25 | git: https://github.com/NodleCode/chain 26 | branch: master 27 | package: nodle-parachain 28 | name: nodle-chain 29 | tag: latest 30 | flags: 31 | - 32 | binary: polkadot 33 | git: https://github.com/paritytech/polkadot 34 | branch: master 35 | package: polkadot 36 | name: polkadot 37 | tag: latest 38 | flags: 39 | - 40 | binary: edgeware 41 | git: https://github.com/edgeware-network/edgeware-node 42 | branch: master 43 | package: edgeware-cli 44 | name: edgeware 45 | tag: latest 46 | flags: 47 | 48 | runs-on: ubuntu-latest 49 | steps: 50 | - 51 | name: Checkout 52 | uses: actions/checkout@v3.3.0 53 | - 54 | name: Set up Docker Buildx 55 | uses: docker/setup-buildx-action@v2.4.0 56 | - 57 | name: Login to DockerHub 58 | if: github.event_name != 'pull_request' 59 | uses: docker/login-action@v1.10.0 60 | with: 61 | username: ${{ secrets.DOCKERHUB_USERNAME }} 62 | password: ${{ secrets.DOCKERHUB_TOKEN }} 63 | - 64 | name: Build and push 65 | uses: docker/build-push-action@v4.0.0 66 | with: 67 | context: ./substrate 68 | file: ./substrate/Dockerfile 69 | push: ${{ github.event_name != 'pull_request' }} 70 | cache-from: type=local,src=/tmp/.buildx-cache 71 | cache-to: type=local,dest=/tmp/.buildx-cache 72 | tags: eteissonniere/${{ matrix.name }}:${{ matrix.tag }} 73 | build-args: | 74 | GIT_REPO=${{ matrix.git }} 75 | GIT_BRANCH=${{ matrix.branch }} 76 | PACKAGE_NAME=${{ matrix.package }} 77 | BINARY_NAME=${{ matrix.binary }} 78 | FLAGS=${{ matrix.flags }} 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Substrate Node OPs 2 | ✨ This repo contains everything you need to deploy and manage substrate based nodes! ✨ 3 | 4 | So far, we have: 5 | - a suite of docker containers being built everyday and pushed to [the docker hub](https://hub.docker.com/u/eteissonniere) 6 | - self configuring images for both prometheus and grafana 7 | - a built in grafana dashboard to monitor your nodes 8 | - templates to deploy on your own cloud provider through [moncc](https://moncc.io/) 9 | 10 | > If you'd like to see how you can use this project to deploy your own nodes please check our [recent medium post](https://medium.com/@eliott_t/ce2ddc001e65?source=friends_link&sk=be285141f01ddd0d66733f6d014abfbd). 11 | 12 | ![Grafana Dashboard](https://user-images.githubusercontent.com/10683430/95597134-8d57cb00-0a4e-11eb-8ade-af105ec86ed7.png) 13 | 14 | # Contributing 15 | 16 | ## How to add your own substrate node 17 | If you are running a substrate based chain and would your node to be included in our build suite follow these steps: 18 | 1. Fork this repo 19 | 2. Edit `./.github/workflows/substrate.yml` to include the details of your project 20 | 3. Create a pull request, if it is accepted we will create the repo on our docker hub account 21 | 4. Profit! -------------------------------------------------------------------------------- /grafana/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM grafana/grafana:7.2.0 2 | 3 | USER root 4 | RUN chown grafana:grafana -R /etc/grafana/provisioning 5 | RUN mkdir -p /var/lib/grafana/dashboards 6 | 7 | USER grafana 8 | COPY ./entrypoint.sh /entrypoint.sh 9 | COPY ./dashboard.json /var/lib/grafana/dashboards/substrate.json 10 | ENTRYPOINT ["/entrypoint.sh"] 11 | -------------------------------------------------------------------------------- /grafana/dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": { 3 | "list": [ 4 | { 5 | "$$hashKey": "object:263", 6 | "builtIn": 1, 7 | "datasource": "-- Grafana --", 8 | "enable": true, 9 | "hide": true, 10 | "iconColor": "rgba(0, 211, 255, 1)", 11 | "limit": 100, 12 | "name": "Annotations & Alerts", 13 | "showIn": 0, 14 | "type": "dashboard" 15 | } 16 | ] 17 | }, 18 | "description": "", 19 | "editable": true, 20 | "gnetId": 12425, 21 | "graphTooltip": 0, 22 | "iteration": 1602160575711, 23 | "links": [], 24 | "panels": [ 25 | { 26 | "cacheTimeout": null, 27 | "datasource": "Prometheus", 28 | "fieldConfig": { 29 | "defaults": { 30 | "custom": {}, 31 | "links": [ 32 | { 33 | "title": "", 34 | "url": "" 35 | } 36 | ], 37 | "mappings": [ 38 | { 39 | "id": 0, 40 | "op": "=", 41 | "text": "Stuck", 42 | "type": 1, 43 | "value": "1492283" 44 | } 45 | ], 46 | "nullValueMode": "connected", 47 | "thresholds": { 48 | "mode": "absolute", 49 | "steps": [ 50 | { 51 | "color": "rgb(222, 101, 171)", 52 | "value": null 53 | } 54 | ] 55 | }, 56 | "unit": "locale" 57 | }, 58 | "overrides": [] 59 | }, 60 | "gridPos": { 61 | "h": 6, 62 | "w": 14, 63 | "x": 0, 64 | "y": 0 65 | }, 66 | "id": 6, 67 | "links": [], 68 | "options": { 69 | "colorMode": "background", 70 | "graphMode": "area", 71 | "justifyMode": "center", 72 | "orientation": "vertical", 73 | "reduceOptions": { 74 | "calcs": [ 75 | "last" 76 | ], 77 | "fields": "", 78 | "values": false 79 | }, 80 | "textMode": "auto" 81 | }, 82 | "pluginVersion": "7.2.0", 83 | "targets": [ 84 | { 85 | "expr": "substrate_block_height{instance=~'$node'}", 86 | "instant": false, 87 | "interval": "", 88 | "legendFormat": "{{status}}", 89 | "refId": "B" 90 | } 91 | ], 92 | "timeFrom": null, 93 | "timeShift": null, 94 | "title": "Height of the chain", 95 | "type": "stat" 96 | }, 97 | { 98 | "cacheTimeout": null, 99 | "datasource": "Prometheus", 100 | "fieldConfig": { 101 | "defaults": { 102 | "custom": {}, 103 | "mappings": [ 104 | { 105 | "id": 0, 106 | "op": "=", 107 | "text": "N/A", 108 | "type": 1, 109 | "value": "null" 110 | } 111 | ], 112 | "nullValueMode": "connected", 113 | "thresholds": { 114 | "mode": "absolute", 115 | "steps": [ 116 | { 117 | "color": "semi-dark-blue", 118 | "value": null 119 | } 120 | ] 121 | }, 122 | "unit": "bytes" 123 | }, 124 | "overrides": [] 125 | }, 126 | "gridPos": { 127 | "h": 6, 128 | "w": 10, 129 | "x": 14, 130 | "y": 0 131 | }, 132 | "id": 8, 133 | "links": [], 134 | "options": { 135 | "colorMode": "background", 136 | "graphMode": "area", 137 | "justifyMode": "auto", 138 | "orientation": "vertical", 139 | "reduceOptions": { 140 | "calcs": [ 141 | "last" 142 | ], 143 | "fields": "", 144 | "values": false 145 | }, 146 | "textMode": "auto" 147 | }, 148 | "pluginVersion": "7.2.0", 149 | "targets": [ 150 | { 151 | "expr": "rate(substrate_sub_libp2p_network_bytes_total{instance='$node'}[5m])", 152 | "interval": "", 153 | "legendFormat": "{{direction}}", 154 | "refId": "A" 155 | } 156 | ], 157 | "timeFrom": null, 158 | "timeShift": null, 159 | "title": "Networking bytes per second", 160 | "type": "stat" 161 | }, 162 | { 163 | "aliasColors": {}, 164 | "bars": false, 165 | "dashLength": 10, 166 | "dashes": false, 167 | "datasource": "Prometheus", 168 | "description": "", 169 | "fieldConfig": { 170 | "defaults": { 171 | "custom": {}, 172 | "links": [] 173 | }, 174 | "overrides": [] 175 | }, 176 | "fill": 1, 177 | "fillGradient": 0, 178 | "gridPos": { 179 | "h": 8, 180 | "w": 12, 181 | "x": 0, 182 | "y": 6 183 | }, 184 | "hiddenSeries": false, 185 | "id": 30, 186 | "legend": { 187 | "avg": false, 188 | "current": false, 189 | "max": false, 190 | "min": false, 191 | "show": true, 192 | "total": false, 193 | "values": false 194 | }, 195 | "lines": true, 196 | "linewidth": 1, 197 | "nullPointMode": "null", 198 | "options": { 199 | "alertThreshold": true 200 | }, 201 | "percentage": false, 202 | "pluginVersion": "7.2.0", 203 | "pointradius": 2, 204 | "points": false, 205 | "renderer": "flot", 206 | "seriesOverrides": [], 207 | "spaceLength": 10, 208 | "stack": false, 209 | "steppedLine": false, 210 | "targets": [ 211 | { 212 | "expr": "rate(substrate_tasks_polling_duration_bucket{instance='$node'}[5m])", 213 | "interval": "", 214 | "legendFormat": "{{task_name}}", 215 | "refId": "A" 216 | } 217 | ], 218 | "thresholds": [], 219 | "timeFrom": null, 220 | "timeRegions": [], 221 | "timeShift": null, 222 | "title": "Tasks rate", 223 | "tooltip": { 224 | "shared": true, 225 | "sort": 0, 226 | "value_type": "individual" 227 | }, 228 | "type": "graph", 229 | "xaxis": { 230 | "buckets": null, 231 | "mode": "time", 232 | "name": null, 233 | "show": true, 234 | "values": [] 235 | }, 236 | "yaxes": [ 237 | { 238 | "$$hashKey": "object:2314", 239 | "format": "short", 240 | "label": null, 241 | "logBase": 1, 242 | "max": null, 243 | "min": null, 244 | "show": true 245 | }, 246 | { 247 | "$$hashKey": "object:2315", 248 | "format": "short", 249 | "label": null, 250 | "logBase": 1, 251 | "max": null, 252 | "min": null, 253 | "show": true 254 | } 255 | ], 256 | "yaxis": { 257 | "align": false, 258 | "alignLevel": null 259 | } 260 | }, 261 | { 262 | "aliasColors": {}, 263 | "bars": false, 264 | "dashLength": 10, 265 | "dashes": false, 266 | "datasource": "Prometheus", 267 | "fieldConfig": { 268 | "defaults": { 269 | "custom": {}, 270 | "links": [] 271 | }, 272 | "overrides": [] 273 | }, 274 | "fill": 1, 275 | "fillGradient": 0, 276 | "gridPos": { 277 | "h": 8, 278 | "w": 12, 279 | "x": 12, 280 | "y": 6 281 | }, 282 | "hiddenSeries": false, 283 | "id": 14, 284 | "legend": { 285 | "alignAsTable": false, 286 | "avg": false, 287 | "current": false, 288 | "max": false, 289 | "min": false, 290 | "rightSide": false, 291 | "show": true, 292 | "total": false, 293 | "values": false 294 | }, 295 | "lines": true, 296 | "linewidth": 1, 297 | "nullPointMode": "null", 298 | "options": { 299 | "alertThreshold": true 300 | }, 301 | "percentage": false, 302 | "pluginVersion": "7.2.0", 303 | "pointradius": 2, 304 | "points": false, 305 | "renderer": "flot", 306 | "seriesOverrides": [], 307 | "spaceLength": 10, 308 | "stack": false, 309 | "steppedLine": false, 310 | "targets": [ 311 | { 312 | "expr": "rate(substrate_tasks_polling_started_total{instance='$node'}[1m]) - rate(substrate_tasks_polling_duration_count{instance='$node'}[1m])", 313 | "interval": "", 314 | "legendFormat": "{{task_name}}", 315 | "refId": "A" 316 | } 317 | ], 318 | "thresholds": [], 319 | "timeFrom": null, 320 | "timeRegions": [], 321 | "timeShift": null, 322 | "title": "Running Tasks", 323 | "tooltip": { 324 | "shared": true, 325 | "sort": 0, 326 | "value_type": "individual" 327 | }, 328 | "type": "graph", 329 | "xaxis": { 330 | "buckets": null, 331 | "mode": "time", 332 | "name": null, 333 | "show": true, 334 | "values": [] 335 | }, 336 | "yaxes": [ 337 | { 338 | "$$hashKey": "object:956", 339 | "format": "short", 340 | "label": null, 341 | "logBase": 1, 342 | "max": null, 343 | "min": null, 344 | "show": true 345 | }, 346 | { 347 | "$$hashKey": "object:957", 348 | "format": "short", 349 | "label": null, 350 | "logBase": 1, 351 | "max": null, 352 | "min": null, 353 | "show": true 354 | } 355 | ], 356 | "yaxis": { 357 | "align": false, 358 | "alignLevel": null 359 | } 360 | }, 361 | { 362 | "aliasColors": {}, 363 | "bars": false, 364 | "dashLength": 10, 365 | "dashes": false, 366 | "datasource": "Prometheus", 367 | "description": "", 368 | "fieldConfig": { 369 | "defaults": { 370 | "custom": {}, 371 | "links": [] 372 | }, 373 | "overrides": [] 374 | }, 375 | "fill": 1, 376 | "fillGradient": 0, 377 | "gridPos": { 378 | "h": 8, 379 | "w": 12, 380 | "x": 0, 381 | "y": 14 382 | }, 383 | "hiddenSeries": false, 384 | "id": 10, 385 | "legend": { 386 | "alignAsTable": false, 387 | "avg": true, 388 | "current": true, 389 | "max": true, 390 | "min": true, 391 | "show": true, 392 | "total": false, 393 | "values": true 394 | }, 395 | "lines": true, 396 | "linewidth": 1, 397 | "nullPointMode": "null", 398 | "options": { 399 | "alertThreshold": true 400 | }, 401 | "percentage": false, 402 | "pluginVersion": "7.2.0", 403 | "pointradius": 2, 404 | "points": false, 405 | "renderer": "flot", 406 | "seriesOverrides": [], 407 | "spaceLength": 10, 408 | "stack": false, 409 | "steppedLine": false, 410 | "targets": [ 411 | { 412 | "expr": "substrate_sub_libp2p_peers_count{instance='$node'}", 413 | "instant": false, 414 | "interval": "", 415 | "legendFormat": "Peers count", 416 | "refId": "A" 417 | }, 418 | { 419 | "expr": "substrate_sub_libp2p_peerset_num_discovered{instance='$node'}", 420 | "interval": "", 421 | "legendFormat": "Discovered peers", 422 | "refId": "C" 423 | }, 424 | { 425 | "expr": "substrate_sub_libp2p_peerset_num_requested{instance='$node'}", 426 | "interval": "", 427 | "legendFormat": "Requested peers", 428 | "refId": "B" 429 | } 430 | ], 431 | "thresholds": [], 432 | "timeFrom": null, 433 | "timeRegions": [], 434 | "timeShift": null, 435 | "title": "Peers connected, discovered, and requested", 436 | "tooltip": { 437 | "shared": true, 438 | "sort": 0, 439 | "value_type": "individual" 440 | }, 441 | "type": "graph", 442 | "xaxis": { 443 | "buckets": null, 444 | "mode": "time", 445 | "name": null, 446 | "show": true, 447 | "values": [] 448 | }, 449 | "yaxes": [ 450 | { 451 | "$$hashKey": "object:1204", 452 | "decimals": null, 453 | "format": "none", 454 | "label": "", 455 | "logBase": 1, 456 | "max": null, 457 | "min": null, 458 | "show": true 459 | }, 460 | { 461 | "$$hashKey": "object:1205", 462 | "format": "short", 463 | "label": null, 464 | "logBase": 1, 465 | "max": null, 466 | "min": null, 467 | "show": true 468 | } 469 | ], 470 | "yaxis": { 471 | "align": false, 472 | "alignLevel": null 473 | } 474 | }, 475 | { 476 | "aliasColors": {}, 477 | "bars": false, 478 | "dashLength": 10, 479 | "dashes": false, 480 | "datasource": "Prometheus", 481 | "fieldConfig": { 482 | "defaults": { 483 | "custom": {}, 484 | "links": [] 485 | }, 486 | "overrides": [] 487 | }, 488 | "fill": 1, 489 | "fillGradient": 0, 490 | "gridPos": { 491 | "h": 8, 492 | "w": 12, 493 | "x": 12, 494 | "y": 14 495 | }, 496 | "hiddenSeries": false, 497 | "id": 32, 498 | "legend": { 499 | "avg": false, 500 | "current": false, 501 | "max": false, 502 | "min": false, 503 | "show": false, 504 | "total": false, 505 | "values": false 506 | }, 507 | "lines": true, 508 | "linewidth": 1, 509 | "nullPointMode": "null", 510 | "options": { 511 | "alertThreshold": true 512 | }, 513 | "percentage": false, 514 | "pluginVersion": "7.2.0", 515 | "pointradius": 2, 516 | "points": false, 517 | "renderer": "flot", 518 | "seriesOverrides": [], 519 | "spaceLength": 10, 520 | "stack": false, 521 | "steppedLine": false, 522 | "targets": [ 523 | { 524 | "expr": "substrate_sync_peers{instance='$node'}", 525 | "interval": "", 526 | "legendFormat": "Connected Peers", 527 | "refId": "A" 528 | } 529 | ], 530 | "thresholds": [], 531 | "timeFrom": null, 532 | "timeRegions": [], 533 | "timeShift": null, 534 | "title": "Connected peers", 535 | "tooltip": { 536 | "shared": true, 537 | "sort": 0, 538 | "value_type": "individual" 539 | }, 540 | "type": "graph", 541 | "xaxis": { 542 | "buckets": null, 543 | "mode": "time", 544 | "name": null, 545 | "show": true, 546 | "values": [] 547 | }, 548 | "yaxes": [ 549 | { 550 | "$$hashKey": "object:1308", 551 | "format": "short", 552 | "label": null, 553 | "logBase": 1, 554 | "max": null, 555 | "min": null, 556 | "show": true 557 | }, 558 | { 559 | "$$hashKey": "object:1309", 560 | "format": "short", 561 | "label": null, 562 | "logBase": 1, 563 | "max": null, 564 | "min": null, 565 | "show": true 566 | } 567 | ], 568 | "yaxis": { 569 | "align": false, 570 | "alignLevel": null 571 | } 572 | }, 573 | { 574 | "aliasColors": {}, 575 | "bars": false, 576 | "dashLength": 10, 577 | "dashes": false, 578 | "datasource": "Prometheus", 579 | "fieldConfig": { 580 | "defaults": { 581 | "custom": {}, 582 | "links": [] 583 | }, 584 | "overrides": [] 585 | }, 586 | "fill": 1, 587 | "fillGradient": 0, 588 | "gridPos": { 589 | "h": 8, 590 | "w": 12, 591 | "x": 0, 592 | "y": 22 593 | }, 594 | "hiddenSeries": false, 595 | "id": 26, 596 | "legend": { 597 | "alignAsTable": false, 598 | "avg": false, 599 | "current": false, 600 | "max": false, 601 | "min": false, 602 | "rightSide": false, 603 | "show": true, 604 | "total": false, 605 | "values": false 606 | }, 607 | "lines": true, 608 | "linewidth": 1, 609 | "nullPointMode": "null", 610 | "options": { 611 | "alertThreshold": true 612 | }, 613 | "percentage": false, 614 | "pluginVersion": "7.2.0", 615 | "pointradius": 2, 616 | "points": false, 617 | "renderer": "flot", 618 | "seriesOverrides": [], 619 | "spaceLength": 10, 620 | "stack": false, 621 | "steppedLine": false, 622 | "targets": [ 623 | { 624 | "expr": "substrate_state_db_cache_bytes{instance='$node'}", 625 | "interval": "", 626 | "legendFormat": "{{subtype}}", 627 | "refId": "A" 628 | } 629 | ], 630 | "thresholds": [], 631 | "timeFrom": null, 632 | "timeRegions": [], 633 | "timeShift": null, 634 | "title": "State Cache DB", 635 | "tooltip": { 636 | "shared": true, 637 | "sort": 0, 638 | "value_type": "individual" 639 | }, 640 | "type": "graph", 641 | "xaxis": { 642 | "buckets": null, 643 | "mode": "time", 644 | "name": null, 645 | "show": true, 646 | "values": [] 647 | }, 648 | "yaxes": [ 649 | { 650 | "$$hashKey": "object:1532", 651 | "format": "bytes", 652 | "label": null, 653 | "logBase": 1, 654 | "max": null, 655 | "min": null, 656 | "show": true 657 | }, 658 | { 659 | "$$hashKey": "object:1533", 660 | "format": "short", 661 | "label": null, 662 | "logBase": 1, 663 | "max": null, 664 | "min": null, 665 | "show": true 666 | } 667 | ], 668 | "yaxis": { 669 | "align": false, 670 | "alignLevel": null 671 | } 672 | }, 673 | { 674 | "aliasColors": {}, 675 | "bars": false, 676 | "dashLength": 10, 677 | "dashes": false, 678 | "datasource": "Prometheus", 679 | "fieldConfig": { 680 | "defaults": { 681 | "custom": {}, 682 | "links": [] 683 | }, 684 | "overrides": [] 685 | }, 686 | "fill": 1, 687 | "fillGradient": 0, 688 | "gridPos": { 689 | "h": 8, 690 | "w": 12, 691 | "x": 12, 692 | "y": 22 693 | }, 694 | "hiddenSeries": false, 695 | "id": 18, 696 | "legend": { 697 | "avg": false, 698 | "current": false, 699 | "max": false, 700 | "min": false, 701 | "show": true, 702 | "total": false, 703 | "values": false 704 | }, 705 | "lines": true, 706 | "linewidth": 1, 707 | "nullPointMode": "null", 708 | "options": { 709 | "alertThreshold": true 710 | }, 711 | "percentage": false, 712 | "pluginVersion": "7.2.0", 713 | "pointradius": 2, 714 | "points": false, 715 | "renderer": "flot", 716 | "seriesOverrides": [], 717 | "spaceLength": 10, 718 | "stack": false, 719 | "steppedLine": false, 720 | "targets": [ 721 | { 722 | "expr": "rate(substrate_finality_grandpa_communication_gossip_validator_messages{instance='$node'}[5m])", 723 | "interval": "", 724 | "legendFormat": "{{message}}", 725 | "refId": "A" 726 | } 727 | ], 728 | "thresholds": [], 729 | "timeFrom": null, 730 | "timeRegions": [], 731 | "timeShift": null, 732 | "title": "GRANDPA Validator Messages", 733 | "tooltip": { 734 | "shared": true, 735 | "sort": 0, 736 | "value_type": "individual" 737 | }, 738 | "type": "graph", 739 | "xaxis": { 740 | "buckets": null, 741 | "mode": "time", 742 | "name": null, 743 | "show": true, 744 | "values": [] 745 | }, 746 | "yaxes": [ 747 | { 748 | "$$hashKey": "object:312", 749 | "format": "short", 750 | "label": null, 751 | "logBase": 1, 752 | "max": null, 753 | "min": null, 754 | "show": true 755 | }, 756 | { 757 | "$$hashKey": "object:313", 758 | "format": "short", 759 | "label": null, 760 | "logBase": 1, 761 | "max": null, 762 | "min": null, 763 | "show": true 764 | } 765 | ], 766 | "yaxis": { 767 | "align": false, 768 | "alignLevel": null 769 | } 770 | }, 771 | { 772 | "aliasColors": {}, 773 | "bars": false, 774 | "dashLength": 10, 775 | "dashes": false, 776 | "datasource": "Prometheus", 777 | "fieldConfig": { 778 | "defaults": { 779 | "custom": {}, 780 | "links": [] 781 | }, 782 | "overrides": [] 783 | }, 784 | "fill": 1, 785 | "fillGradient": 0, 786 | "gridPos": { 787 | "h": 8, 788 | "w": 12, 789 | "x": 0, 790 | "y": 30 791 | }, 792 | "hiddenSeries": false, 793 | "id": 24, 794 | "legend": { 795 | "avg": false, 796 | "current": false, 797 | "max": false, 798 | "min": false, 799 | "show": false, 800 | "total": false, 801 | "values": false 802 | }, 803 | "lines": true, 804 | "linewidth": 1, 805 | "nullPointMode": "null", 806 | "options": { 807 | "alertThreshold": true 808 | }, 809 | "percentage": false, 810 | "pluginVersion": "7.2.0", 811 | "pointradius": 2, 812 | "points": false, 813 | "renderer": "flot", 814 | "seriesOverrides": [], 815 | "spaceLength": 10, 816 | "stack": false, 817 | "steppedLine": false, 818 | "targets": [ 819 | { 820 | "expr": "substrate_state_cache_bytes{instance='$node'}", 821 | "interval": "", 822 | "legendFormat": "Size", 823 | "refId": "A" 824 | } 825 | ], 826 | "thresholds": [], 827 | "timeFrom": null, 828 | "timeRegions": [], 829 | "timeShift": null, 830 | "title": "State Cache", 831 | "tooltip": { 832 | "shared": true, 833 | "sort": 0, 834 | "value_type": "individual" 835 | }, 836 | "type": "graph", 837 | "xaxis": { 838 | "buckets": null, 839 | "mode": "time", 840 | "name": null, 841 | "show": true, 842 | "values": [] 843 | }, 844 | "yaxes": [ 845 | { 846 | "$$hashKey": "object:1295", 847 | "format": "bytes", 848 | "label": null, 849 | "logBase": 1, 850 | "max": null, 851 | "min": null, 852 | "show": true 853 | }, 854 | { 855 | "$$hashKey": "object:1296", 856 | "format": "short", 857 | "label": null, 858 | "logBase": 1, 859 | "max": null, 860 | "min": null, 861 | "show": true 862 | } 863 | ], 864 | "yaxis": { 865 | "align": false, 866 | "alignLevel": null 867 | } 868 | }, 869 | { 870 | "aliasColors": {}, 871 | "bars": false, 872 | "dashLength": 10, 873 | "dashes": false, 874 | "datasource": "Prometheus", 875 | "fieldConfig": { 876 | "defaults": { 877 | "custom": {}, 878 | "links": [] 879 | }, 880 | "overrides": [] 881 | }, 882 | "fill": 1, 883 | "fillGradient": 0, 884 | "gridPos": { 885 | "h": 8, 886 | "w": 12, 887 | "x": 12, 888 | "y": 30 889 | }, 890 | "hiddenSeries": false, 891 | "id": 16, 892 | "legend": { 893 | "avg": false, 894 | "current": false, 895 | "max": false, 896 | "min": false, 897 | "show": false, 898 | "total": false, 899 | "values": false 900 | }, 901 | "lines": true, 902 | "linewidth": 1, 903 | "nullPointMode": "null", 904 | "options": { 905 | "alertThreshold": true 906 | }, 907 | "percentage": false, 908 | "pluginVersion": "7.2.0", 909 | "pointradius": 2, 910 | "points": false, 911 | "renderer": "flot", 912 | "seriesOverrides": [], 913 | "spaceLength": 10, 914 | "stack": false, 915 | "steppedLine": false, 916 | "targets": [ 917 | { 918 | "expr": "substrate_sync_queued_blocks{instance='$node'}", 919 | "interval": "", 920 | "legendFormat": "Queued Blocks", 921 | "refId": "A" 922 | } 923 | ], 924 | "thresholds": [], 925 | "timeFrom": null, 926 | "timeRegions": [], 927 | "timeShift": null, 928 | "title": "Queued Blocks (sync)", 929 | "tooltip": { 930 | "shared": true, 931 | "sort": 0, 932 | "value_type": "individual" 933 | }, 934 | "type": "graph", 935 | "xaxis": { 936 | "buckets": null, 937 | "mode": "time", 938 | "name": null, 939 | "show": true, 940 | "values": [] 941 | }, 942 | "yaxes": [ 943 | { 944 | "$$hashKey": "object:1594", 945 | "format": "short", 946 | "label": null, 947 | "logBase": 1, 948 | "max": null, 949 | "min": null, 950 | "show": true 951 | }, 952 | { 953 | "$$hashKey": "object:1595", 954 | "format": "short", 955 | "label": null, 956 | "logBase": 1, 957 | "max": null, 958 | "min": null, 959 | "show": true 960 | } 961 | ], 962 | "yaxis": { 963 | "align": false, 964 | "alignLevel": null 965 | } 966 | }, 967 | { 968 | "datasource": "Prometheus", 969 | "fieldConfig": { 970 | "defaults": { 971 | "custom": {}, 972 | "mappings": [], 973 | "thresholds": { 974 | "mode": "absolute", 975 | "steps": [ 976 | { 977 | "color": "green", 978 | "value": null 979 | }, 980 | { 981 | "color": "red", 982 | "value": 80 983 | } 984 | ] 985 | } 986 | }, 987 | "overrides": [] 988 | }, 989 | "gridPos": { 990 | "h": 8, 991 | "w": 12, 992 | "x": 0, 993 | "y": 38 994 | }, 995 | "id": 12, 996 | "options": { 997 | "colorMode": "value", 998 | "graphMode": "area", 999 | "justifyMode": "auto", 1000 | "orientation": "horizontal", 1001 | "reduceOptions": { 1002 | "calcs": [ 1003 | "lastNotNull" 1004 | ], 1005 | "fields": "", 1006 | "values": false 1007 | }, 1008 | "textMode": "auto" 1009 | }, 1010 | "pluginVersion": "7.2.0", 1011 | "targets": [ 1012 | { 1013 | "expr": "substrate_ready_transactions_number{instance='$node'}", 1014 | "interval": "", 1015 | "legendFormat": "Number of transactions in the ready queue", 1016 | "refId": "A" 1017 | } 1018 | ], 1019 | "timeFrom": null, 1020 | "timeShift": null, 1021 | "title": "Number of transactions in the ready queue", 1022 | "type": "stat" 1023 | }, 1024 | { 1025 | "aliasColors": {}, 1026 | "bars": false, 1027 | "dashLength": 10, 1028 | "dashes": false, 1029 | "datasource": "Prometheus", 1030 | "fieldConfig": { 1031 | "defaults": { 1032 | "custom": {}, 1033 | "links": [] 1034 | }, 1035 | "overrides": [] 1036 | }, 1037 | "fill": 1, 1038 | "fillGradient": 0, 1039 | "gridPos": { 1040 | "h": 8, 1041 | "w": 12, 1042 | "x": 12, 1043 | "y": 38 1044 | }, 1045 | "hiddenSeries": false, 1046 | "id": 28, 1047 | "legend": { 1048 | "avg": false, 1049 | "current": false, 1050 | "max": false, 1051 | "min": false, 1052 | "show": false, 1053 | "total": false, 1054 | "values": false 1055 | }, 1056 | "lines": true, 1057 | "linewidth": 1, 1058 | "nullPointMode": "null", 1059 | "options": { 1060 | "alertThreshold": true 1061 | }, 1062 | "percentage": false, 1063 | "pluginVersion": "7.2.0", 1064 | "pointradius": 2, 1065 | "points": false, 1066 | "renderer": "flot", 1067 | "seriesOverrides": [], 1068 | "spaceLength": 10, 1069 | "stack": false, 1070 | "steppedLine": false, 1071 | "targets": [ 1072 | { 1073 | "expr": "substrate_number_leaves{instance='$node'}", 1074 | "interval": "", 1075 | "legendFormat": "Number of Leaves", 1076 | "refId": "A" 1077 | } 1078 | ], 1079 | "thresholds": [], 1080 | "timeFrom": null, 1081 | "timeRegions": [], 1082 | "timeShift": null, 1083 | "title": "Number of Leaves", 1084 | "tooltip": { 1085 | "shared": true, 1086 | "sort": 0, 1087 | "value_type": "individual" 1088 | }, 1089 | "type": "graph", 1090 | "xaxis": { 1091 | "buckets": null, 1092 | "mode": "time", 1093 | "name": null, 1094 | "show": true, 1095 | "values": [] 1096 | }, 1097 | "yaxes": [ 1098 | { 1099 | "$$hashKey": "object:1848", 1100 | "format": "short", 1101 | "label": null, 1102 | "logBase": 1, 1103 | "max": null, 1104 | "min": null, 1105 | "show": true 1106 | }, 1107 | { 1108 | "$$hashKey": "object:1849", 1109 | "format": "short", 1110 | "label": null, 1111 | "logBase": 1, 1112 | "max": null, 1113 | "min": null, 1114 | "show": true 1115 | } 1116 | ], 1117 | "yaxis": { 1118 | "align": false, 1119 | "alignLevel": null 1120 | } 1121 | } 1122 | ], 1123 | "refresh": "10s", 1124 | "schemaVersion": 26, 1125 | "style": "dark", 1126 | "tags": [], 1127 | "templating": { 1128 | "list": [ 1129 | { 1130 | "allValue": null, 1131 | "current": { 1132 | "selected": false, 1133 | "text": "", 1134 | "value": "" 1135 | }, 1136 | "datasource": "Prometheus", 1137 | "definition": "label_values(substrate_block_height, instance)", 1138 | "hide": 0, 1139 | "includeAll": false, 1140 | "label": "Node Instance", 1141 | "multi": false, 1142 | "name": "node", 1143 | "options": [], 1144 | "query": "label_values(substrate_block_height, instance)", 1145 | "refresh": 1, 1146 | "regex": "", 1147 | "skipUrlSync": false, 1148 | "sort": 1, 1149 | "tagValuesQuery": "", 1150 | "tags": [], 1151 | "tagsQuery": "", 1152 | "type": "query", 1153 | "useTags": false 1154 | } 1155 | ] 1156 | }, 1157 | "time": { 1158 | "from": "now-6h", 1159 | "to": "now" 1160 | }, 1161 | "timepicker": { 1162 | "refresh_intervals": [ 1163 | "10s", 1164 | "30s", 1165 | "1m", 1166 | "5m", 1167 | "15m", 1168 | "30m", 1169 | "1h", 1170 | "2h", 1171 | "1d" 1172 | ] 1173 | }, 1174 | "timezone": "", 1175 | "title": "Substrate Node Metrics", 1176 | "uid": "twYeaxRMz", 1177 | "version": 1 1178 | } -------------------------------------------------------------------------------- /grafana/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export CONFIG_DIR=/etc/grafana/provisioning 4 | 5 | cat << EOF > $CONFIG_DIR/datasources/prometheus.yml 6 | apiVersion: 1 7 | deleteDatasources: 8 | - name: Prometheus 9 | orgId: 1 10 | datasources: 11 | - name: Prometheus 12 | type: prometheus 13 | access: proxy 14 | orgId: 1 15 | url: $1 16 | isDefault: true 17 | version: 1 18 | editable: false 19 | EOF 20 | 21 | cat << EOF > $CONFIG_DIR/dashboards/substrate.yml 22 | apiVersion: 1 23 | providers: 24 | - name: Prometheus 25 | orgId: 1 26 | allowUiUpdates: false 27 | disableDeletion: false 28 | options: 29 | path: /var/lib/grafana/dashboards 30 | EOF 31 | 32 | /run.sh -------------------------------------------------------------------------------- /monk/README.md: -------------------------------------------------------------------------------- 1 | ## Examples 2 | 3 | ### Start a local rococo testnet 4 | > We assume you have a cluster named `roco` running. 5 | 6 | ``` 7 | monk load core/* hub/rococo/* hub/stack.yml 8 | monk run -t roco eteissonniere/roc 9 | ``` -------------------------------------------------------------------------------- /monk/core/grafana.yml: -------------------------------------------------------------------------------- 1 | namespace: /eteissonniere 2 | grafana: 3 | defines: runnable 4 | containers: 5 | defines: containers 6 | grafana: 7 | image: docker.io/eteissonniere/substrate-grafana 8 | image-tag: latest 9 | entrypoint: <- `/entrypoint.sh ${prometheus-endpoint}` 10 | ports: 11 | - 0.0.0.0:80:3000 12 | environment: 13 | - <- `GF_SECURITY_ADMIN_PASSWORD=${password}` 14 | paths: 15 | - <- `${moncc-volume-path}/grafana:/var/lib/grafana grafana/grafana` 16 | variables: 17 | defines: variables 18 | prometheus-endpoint: 19 | type: string 20 | value: "" 21 | password: 22 | type: string 23 | value: "password" -------------------------------------------------------------------------------- /monk/core/prometheus.yml: -------------------------------------------------------------------------------- 1 | namespace: /eteissonniere 2 | prometheus: 3 | defines: runnable 4 | containers: 5 | defines: containers 6 | prometheus: 7 | image: docker.io/eteissonniere/substrate-prometheus 8 | image-tag: latest 9 | user: root 10 | entrypoint: <- `/entrypoint.sh ${target-nodes}` 11 | paths: 12 | - <- `${moncc-volume-path}/prometheus:/data` 13 | ports: 14 | - 0.0.0.0:9090:9090 15 | variables: 16 | defines: variables 17 | target-nodes: 18 | type: string 19 | value: "" 20 | node-port: 21 | type: int 22 | value: 9615 -------------------------------------------------------------------------------- /monk/core/substrate.yml: -------------------------------------------------------------------------------- 1 | namespace: /eteissonniere 2 | substrate: 3 | defines: runnable 4 | containers: 5 | defines: containers 6 | node: 7 | image: docker.io/eteissonniere/polkadot 8 | image-tag: latest 9 | user: root 10 | entrypoint: <- `${bin} --wasm-execution compiled --name ${node-name} --unsafe-ws-external --unsafe-rpc-external --rpc-external --rpc-cors all --ws-external --ws-port ${wsrpc-port} --port ${p2p-port} --chain ${chain} --prometheus-external --prometheus-port ${prometheus-port} -d /data ${cmds}` 11 | paths: 12 | - <- `${moncc-volume-path}/${node-name}:/data` 13 | ports: 14 | - <- `0.0.0.0:${p2p-port}:${p2p-port}` 15 | - <- `0.0.0.0:${wsrpc-port}:${wsrpc-port}` 16 | - <- `0.0.0.0:${prometheus-port}:${prometheus-port}` 17 | variables: 18 | defines: variables 19 | wsrpc-port: 20 | type: int 21 | value: 9944 22 | p2p-port: 23 | type: int 24 | value: 30333 25 | prometheus-port: 26 | type: int 27 | value: 9615 28 | node-name: 29 | type: string 30 | value: "substrate" 31 | chain: 32 | type: string 33 | value: "local" 34 | bin: 35 | type: string 36 | value: "node" 37 | cmds: 38 | type: string 39 | value: "" -------------------------------------------------------------------------------- /monk/examples/lb_nodes.yml: -------------------------------------------------------------------------------- 1 | namespace: /eteissonniere 2 | lbdemo-node-a: 3 | defines: runnable 4 | inherits: ./substrate 5 | containers: 6 | node: 7 | image: docker.io/eteissonniere/polkadot 8 | image-tag: latest 9 | variables: 10 | node-name: 11 | value: "lbdemo-gateway-a" 12 | chain: 13 | value: "polkadot" 14 | lbdemo-node-b: 15 | defines: runnable 16 | inherits: ./substrate 17 | containers: 18 | node: 19 | image: docker.io/eteissonniere/polkadot 20 | image-tag: latest 21 | variables: 22 | node-name: "lbdemo-gateway-b" 23 | chain: "polkadot" 24 | 25 | lbdemo-monitoring-prometheus: 26 | defines: runnable 27 | inherits: ./prometheus 28 | variables: 29 | target-nodes: <- get-hostname("eteissonniere/lbdemo-node-a", "node") `:${node-port}` " " get-hostname("eteissonniere/lbdemo-node-b", "node") `:${node-port}` concat-all 30 | 31 | lbdemo-monitoring-grafana: 32 | defines: runnable 33 | inherits: ./grafana 34 | variables: 35 | prometheus-endpoint: <- "http://" get-hostname("eteissonniere/lbdemo-monitoring-prometheus", "prometheus") ":9090" concat-all 36 | 37 | lbdemo: 38 | defines: process-group 39 | balancers: 40 | defines: balancers 41 | app-balancer: 42 | port: 9944 43 | type: http 44 | health-check: 45 | kind: tcp 46 | request: "" 47 | interval: 5 48 | response: "" 49 | instances: 50 | - eteissonniere/lbdemo-node-a 51 | - eteissonniere/lbdemo-node-b 52 | runnable-list: 53 | - eteissonniere/lbdemo-node-a 54 | - eteissonniere/lbdemo-node-b 55 | - eteissonniere/lbdemo-monitoring-prometheus 56 | - eteissonniere/lbdemo-monitoring-grafana 57 | -------------------------------------------------------------------------------- /monk/hub/stack.yml: -------------------------------------------------------------------------------- 1 | namespace: /eteissonniere 2 | 3 | roc-alice: 4 | defines: runnable 5 | inherits: ./roc-substrate 6 | variables: 7 | node-name: roc-alice 8 | cmds: "--alice --node-key 0000000000000000000000000000000000000000000000000000000000000001" 9 | 10 | roc-bob: 11 | defines: runnable 12 | inherits: ./roc-substrate 13 | variables: 14 | node-name: roc-bob 15 | cmds: <- "--bob --bootnodes /dns/" get-hostname("eteissonniere/roc-alice", "node") "/tcp/30333/p2p/12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp" concat-all 16 | 17 | roc-monitoring-prometheus: 18 | defines: runnable 19 | inherits: ./prometheus 20 | variables: 21 | target-nodes: <- get-hostname("eteissonniere/roc-alice", "node") `:${node-port}` " " get-hostname("eteissonniere/roc-bob", "node") `:${node-port}` concat-all 22 | 23 | roc-monitoring-grafana: 24 | defines: runnable 25 | inherits: ./grafana 26 | variables: 27 | prometheus-endpoint: <- "http://" get-hostname("eteissonniere/roc-monitoring-prometheus", "prometheus") ":9090" concat-all 28 | 29 | roc: 30 | defines: process-group 31 | runnable-list: 32 | - eteissonniere/roc-alice 33 | - eteissonniere/roc-bob 34 | - eteissonniere/roc-monitoring-prometheus 35 | - eteissonniere/roc-monitoring-grafana 36 | 37 | roc-alice-local: 38 | defines: runnable 39 | inherits: ./roc-alice 40 | 41 | roc-bob-local: 42 | defines: runnable 43 | inherits: ./roc-bob 44 | variables: 45 | wsrpc-port: 9945 46 | p2p-port: 30334 47 | prometheus-port: 9616 48 | cmds: <- "--bob --bootnodes /dns/" get-hostname("eteissonniere/roc-alice-local", "node") "/tcp/30333/p2p/12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp" concat-all 49 | 50 | roc-local: 51 | defines: process-group 52 | runnable-list: 53 | - eteissonniere/roc-alice-local 54 | - eteissonniere/roc-bob-local 55 | - eteissonniere/roc-monitoring-prometheus 56 | - eteissonniere/roc-monitoring-grafana 57 | -------------------------------------------------------------------------------- /prometheus/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM prom/prometheus:v2.21.0 2 | 3 | COPY ./entrypoint.sh /entrypoint.sh 4 | 5 | USER root 6 | RUN mkdir /data && chown nobody:nogroup /data 7 | 8 | USER nobody 9 | ENTRYPOINT ["/entrypoint.sh"] -------------------------------------------------------------------------------- /prometheus/config.yml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 15s 3 | evaluation_interval: 15s 4 | 5 | scrape_configs: 6 | - job_name: "prometheus" 7 | scrape_interval: 5s 8 | static_configs: 9 | - targets: ["localhost:9090"] 10 | - job_name: "substrate_node" 11 | scrape_interval: 5s 12 | static_configs: 13 | - targets: [ "test1" , "test2" , "test3" , "test4" ] 14 | -------------------------------------------------------------------------------- /prometheus/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export TARGET_STRING="[" 4 | for target in $@; do 5 | if [ "$1" = "$target" ]; then 6 | separator="" 7 | else 8 | separator="," 9 | fi 10 | export TARGET_STRING="$TARGET_STRING $separator \"$target\" " 11 | done 12 | export TARGET_STRING="$TARGET_STRING ]" 13 | 14 | echo $TARGET_STRING 15 | 16 | cat << EOF > config.yml 17 | global: 18 | scrape_interval: 15s 19 | evaluation_interval: 15s 20 | 21 | scrape_configs: 22 | - job_name: "prometheus" 23 | scrape_interval: 5s 24 | static_configs: 25 | - targets: ["localhost:9090"] 26 | - job_name: "substrate_nodes" 27 | scrape_interval: 5s 28 | static_configs: 29 | - targets: $TARGET_STRING 30 | EOF 31 | 32 | echo "configuration written!" 33 | 34 | chmod 0777 config.yml 35 | prometheus --config.file `pwd`/config.yml --storage.tsdb.path /data --web.listen-address="0.0.0.0:9090" 36 | -------------------------------------------------------------------------------- /substrate/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu as builder 2 | 3 | LABEL maintainer="eliott@nuclei.studio" 4 | 5 | ARG PROFILE=release 6 | ARG GIT_REPO 7 | ARG GIT_BRANCH 8 | ARG BINARY_NAME 9 | ARG PACKAGE_NAME 10 | ARG FLAGS 11 | 12 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \ 13 | clang \ 14 | cmake \ 15 | curl \ 16 | git \ 17 | libssl-dev \ 18 | pkg-config \ 19 | protobuf-compiler 20 | 21 | RUN curl https://sh.rustup.rs -sSf | sh -s -- -y && \ 22 | export PATH=$PATH:$HOME/.cargo/bin && \ 23 | git clone ${GIT_REPO} source && \ 24 | cd source && \ 25 | git checkout ${GIT_BRANCH} && \ 26 | git submodule update --init --recursive && \ 27 | rustup default stable && \ 28 | rustup toolchain install nightly && \ 29 | rustup target add wasm32-unknown-unknown --toolchain nightly && \ 30 | cargo build -p ${PACKAGE_NAME} --${PROFILE} ${FLAGS} && \ 31 | cp target/${PROFILE}/${BINARY_NAME} /node 32 | 33 | # ===== SECOND STAGE ====== 34 | 35 | FROM ubuntu 36 | 37 | COPY --from=builder /node /usr/local/bin 38 | 39 | # install curl in the event we want to interact with the local rpc 40 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y curl 41 | RUN useradd --create-home runner 42 | 43 | USER runner 44 | EXPOSE 30333 9933 9944 45 | 46 | ENTRYPOINT ["node"] 47 | --------------------------------------------------------------------------------