{"id":633,"date":"2023-11-22T04:46:44","date_gmt":"2023-11-22T04:46:44","guid":{"rendered":"https:\/\/blog.ngocha.biz\/?p=633"},"modified":"2023-11-22T04:46:44","modified_gmt":"2023-11-22T04:46:44","slug":"setup-prometheus-using-docker","status":"publish","type":"post","link":"https:\/\/blog.ngocha.biz\/?p=633","title":{"rendered":"Setting Up Prometheus Using Docker Compose &#038; Terraform"},"content":{"rendered":"<p>This blog covers the step-by-step guide to setting up the Prometheus Stack, which contains Prometheus, Grafana, and Alert Manager, using Docker and Docker Compose.<\/p>\n<p>It is a learning project that is part of the <a href=\"https:\/\/devopscube.com\/devops-projects\/\">DevOps projects<\/a> initiative.<\/p>\n<p>To understand the basics of observability, please read the <a href=\"https:\/\/devopscube.com\/what-is-observability\/\">Observability guide.<\/a><\/p>\n<h2 id=\"devops-tools-service-used\">DevOps Tools \/ Service Used<\/h2>\n<p>In this setup, we have used the following open-source DevOps tools.<\/p>\n<ol>\n<li><a href=\"https:\/\/devopscube.com\/create-dockerfile-using-docker-init\/\" rel=\"noreferrer\">Docker<\/a><\/li>\n<li>Prometheus<\/li>\n<li>Alert Manager<\/li>\n<li>Grafana<\/li>\n<li><a href=\"https:\/\/devopscube.com\/node-exporter-kubernetes\/\" rel=\"noreferrer\">Prometheus Node Exporter<\/a><\/li>\n<li>Terraform<\/li>\n<\/ol>\n<p>The following are the AWS services used.<\/p>\n<ol>\n<li>ec2<\/li>\n<\/ol>\n<p>The following are the Linux concepts covered as part of the setup<\/p>\n<ol>\n<li><strong>Makefile<\/strong>: Used to modify the server IP address in Prometheus config.<\/li>\n<li><strong>Linux SWAP: <\/strong>To add swap to the EC2 instance.<\/li>\n<li><strong>Shell Scripts:<\/strong> To install Docker, Docker compose and add swap as part of ec2 system startup.<\/li>\n<\/ol>\n<h2 id=\"setup-prerequisites\">Setup Prerequisites<\/h2>\n<p>To deploy the Prometheus stack using Docker Compose, we have the following prerequisites:<\/p>\n<ol>\n<li>AWS Account with a key pair.<\/li>\n<li>AWS CLI configured with the account.<\/li>\n<li>Terraform is installed on your local machine.<\/li>\n<\/ol>\n<h2 id=\"prometheus-stack-architecture-workflow\">Prometheus Stack Architecture &amp; Workflow<\/h2>\n<p>Here is the high-level overview of our setup architecture and workflow.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-113-8.png\" class=\"kg-image\" alt=\"Prometheus Stack Architecture &amp; Workflow\" loading=\"lazy\" width=\"1341\" height=\"1024\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-113-8.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-113-8.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-113-8.png 1341w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>In our setup, we will be using the following components.<\/p>\n<h3 id=\"1-prometheus\">1. Prometheus<\/h3>\n<p>Prometheus is used to scrape the data metrics, pulled from exporters like node exporters. It used to provide metrics to Grafana. It also has a TSDB(Time series database) for storing the metrics. For more info please visit the <a href=\"https:\/\/prometheus.io\/docs\/introduction\/overview\/?ref=devopscube.com\" rel=\"noreferrer noopener\">Prometheus Documentation.<\/a><\/p>\n<h3 id=\"2-alert-manager\">2. Alert Manager<\/h3>\n<p>Alert manager is a component of Prometheus that helps us to configure alerts based on rules using a config file. We can notify the alerts using any medium like email, Slack, chats, etc.<\/p>\n<p>With a nice dashboard where all alerts can be seen from the prometheus dashboard. For more info, please visit <a href=\"https:\/\/prometheus.io\/docs\/alerting\/latest\/alertmanager\/?ref=devopscube.com\" rel=\"noreferrer noopener\">alert manager documentation<\/a><\/p>\n<h3 id=\"3-node-exporter\">3. Node Exporter<\/h3>\n<p><a href=\"https:\/\/devopscube.com\/node-exporter-kubernetes\/\">Node exporter<\/a> is the Prometheus agent that fetches the node metrics and makes it available for Prometheus to fetch from <strong><code>\/metrics<\/code><\/strong> endpoint. So basically node exporter collects all the server-level metrics such as CPU, memory, etc.<\/p>\n<p>While other custom agents are still available and can be used for pushing metrics to prometheus. For more info, please visit<a href=\"https:\/\/prometheus.io\/docs\/guides\/node-exporter\/?ref=devopscube.com\" rel=\"noreferrer noopener\"> Node Exporter Documentation<\/a><\/p>\n<h3 id=\"4-grafana\">4. Grafana<\/h3>\n<p><a href=\"https:\/\/devopscube.com\/integrate-visualize-prometheus-grafana\/\" rel=\"noreferrer noopener\">Grafana<\/a> is a Data visualization tool that fetches the metrics from Prometheus and displays them as colorful and useful dashboards.<\/p>\n<p>It can be integrated with almost all available tools in the market. For more info please visit <a href=\"https:\/\/grafana.com\/docs\/grafana\/latest\/?ref=devopscube.com\" rel=\"noreferrer noopener\">Grafana Official Documentation<\/a><\/p>\n<p>To deploy the Prometheus stack, we will be using the following <a href=\"https:\/\/devopscube.com\/best-devops-tools\/\">DevOps Tools<\/a><\/p>\n<h3 id=\"1-terraform\">1. Terraform<\/h3>\n<p>Terraform is one of the most popular Infrastructure as a Code tools created by HashiCorp. It allows developers to provide the entire infrastructure with code. Please refer to this<a href=\"https:\/\/devopscube.com\/category\/devops\/terraform\/\" rel=\"noreferrer noopener\"> terraform-archives<\/a> for more related blogs.<\/p>\n<p>We will use Terraform to provision the EC2 instance required for the setup.<\/p>\n<h3 id=\"2-docker\">2. Docker<\/h3>\n<p>Docker is a tool for packaging, deploying, and running applications in lightweight. If you want to learn about the basics of Docker, refer to the<a href=\"https:\/\/devopscube.com\/what-is-docker\/\" rel=\"noreferrer noopener\"> Docker basics<\/a> blog.<\/p>\n<p>We will deploy Prometheus components and Grafana on Docker containers.<\/p>\n<h3 id=\"3-docker-compose\">3. Docker Compose<\/h3>\n<p>A Docker-based utility to run a multi-container Docker application. It allows you to define and configure the application&#8217;s services, networks, and volumes in a simple, human-readable YAML file.<\/p>\n<h2 id=\"project-iac-code-explained\">Project IaC Code Explained<\/h2>\n<p>All the IaC codes and configs used in this setup are hosted on the DevOps Projects Github repository.<\/p>\n<p>Clone the <a href=\"https:\/\/github.com\/techiescamp\/devops-projects?ref=devopscube.com\" rel=\"noreferrer noopener\">DevOps projects repository<\/a> to your workstation to follow the guide.<\/p>\n<pre><code>git clone https:\/\/github.com\/techiescamp\/devops-projects<\/code><\/pre>\n<p>The project code is present in the 04-prometheus-observability-stack folder. cd into the folder.<\/p>\n<pre><code>cd 04-prometheus-observability-stack<\/code><\/pre>\n<blockquote><p><strong>Note: <\/strong>Use visual studio code or relevant IDE to understand the code structure better.<\/p><\/blockquote>\n<p>Here is the project structure and config files.<\/p>\n<pre><code>.\n\u251c\u2500\u2500 LICENSE\n\u251c\u2500\u2500 Makefile\n\u251c\u2500\u2500 README.md\n\u251c\u2500\u2500 SECURITY.md\n\u251c\u2500\u2500 alertmanager\n\u2502   \u2514\u2500\u2500 alertmanager.yml\n\u251c\u2500\u2500 docker-compose.yml\n\u251c\u2500\u2500 prometheus\n\u2502   \u251c\u2500\u2500 alertrules.yml\n\u2502   \u251c\u2500\u2500 prometheus.yml\n\u2502   \u2514\u2500\u2500 targets.json\n\u2514\u2500\u2500 terraform-aws\n    \u251c\u2500\u2500 README.md\n    \u251c\u2500\u2500 modules\n    \u2502   \u251c\u2500\u2500 ec2\n    \u2502   \u2502   \u251c\u2500\u2500 main.tf\n    \u2502   \u2502   \u251c\u2500\u2500 outputs.tf\n    \u2502   \u2502   \u251c\u2500\u2500 user-data.sh\n    \u2502   \u2502   \u2514\u2500\u2500 variables.tf\n    \u2502   \u2514\u2500\u2500 security-group\n    \u2502       \u251c\u2500\u2500 main.tf\n    \u2502       \u251c\u2500\u2500 outputs.tf\n    \u2502       \u2514\u2500\u2500 variables.tf\n    \u251c\u2500\u2500 prometheus-stack\n    \u2502   \u251c\u2500\u2500 main.tf\n    \u2502   \u251c\u2500\u2500 outputs.tf\n    \u2502   \u2514\u2500\u2500 variables.tf\n    \u2514\u2500\u2500 vars\n        \u2514\u2500\u2500 ec2.tfvars<\/code><\/pre>\n<p>Let&#8217;s understand the project files.<\/p>\n<p>The <strong>alertmanager<\/strong> folder contains the <strong><code>alertmanager.yml<\/code><\/strong> file which is the configuration file. If you have details of the email, slack, etc. we can update accordingly.<\/p>\n<p>The <strong>Prometheus<\/strong> folder contains <strong><code>alertrules.yml<\/code><\/strong> which is responsible for the alerts to be triggered from Prometheus to the alert manager. <\/p>\n<p>The prometheus.yml config is also mapped to the alert manager endpoint to fetch, and Service discovery is used with the help of a file `file_sd_configs` to scrape the metrics using the <strong><code>targets.json<\/code><\/strong> file.<\/p>\n<p><strong>terraform-aws<\/strong>  directory allows you to manage and isolate resources effectively. Modules contain the reusable Terraform code. These contain the Terraform configuration files (main.tf, outputs.tf, variables.tf) for the respective modules.<\/p>\n<p>The EC2 module also includes <strong><code>user-data.sh<\/code><\/strong> script to bootstrap the EC2 instance with <strong>Docker and Docker Compose<\/strong>. The security group module will create all the inbound &amp; outbound rules required.<\/p>\n<p>Prometheus-stack contains the configuration file <strong>main.tf<\/strong> required for running Terraform. Vars contains an <strong><code>ec2.tfvars<\/code><\/strong> file which contains variable values specific to all the files for the terraform project.<\/p>\n<p>The <strong>Makefile<\/strong> is used to update the provisioned AWS EC2&#8217;s public IP address within the configuration files of <strong><code>prometheus.yml<\/code><\/strong> and <strong><code>targets.json<\/code><\/strong> located in the Prometheus directory.<\/p>\n<p>The <strong><code>docker-compose.yml<\/code><\/strong> file incorporates various services Prometheus, Grafana, Node exporter &amp; Alert Manager. These services are mapped with a network named &#8216;<strong>monitor<\/strong>&#8216; and have an &#8216;<strong>always<\/strong>&#8216; restart flag as well.<\/p>\n<h2 id=\"docker-images\">Docker Images<\/h2>\n<p>We are using the following latest official Docker images available from the Docker Hub Registry.<\/p>\n<ol>\n<li><a href=\"https:\/\/hub.docker.com\/r\/prom\/prometheus?ref=devopscube.com\" rel=\"noreferrer noopener\">prom\/prometheus<\/a><\/li>\n<li><a href=\"https:\/\/hub.docker.com\/r\/grafana\/grafana?ref=devopscube.com\" rel=\"noreferrer noopener\">grafana\/grafana<\/a><\/li>\n<li><a href=\"https:\/\/hub.docker.com\/r\/prom\/node-exporter?ref=devopscube.com\" rel=\"noreferrer noopener\">prom\/node-exporter<\/a><\/li>\n<li><a href=\"https:\/\/hub.docker.com\/r\/prom\/alertmanager?ref=devopscube.com\" rel=\"noreferrer noopener\">prom\/alertmanager<\/a><\/li>\n<\/ol>\n<p>Now that we have learned about the tools and tech and IaC involved in the setup, lets get started with the hands-on installation.<\/p>\n<h2 id=\"provision-server-using-terraform\">Provision Server Using Terraform<\/h2>\n<p>Modify the values of <strong><code>ec2.tfvars<\/code><\/strong> file present in the <strong><code>terraform-aws\/vars<\/code><\/strong> folder. You need to replace the values highlighted in bold with values relevant to your AWS account &amp; region.<\/p>\n<p>If you are using <strong>us-west-2<\/strong>, you can continue with the same AMI ID.<\/p>\n<pre><code># EC2 Instance Variables\nregion         = \"us-west-2\"\nami_id         = \"ami-03fd0aa14bd102718\"\ninstance_type  = \"t4g.micro\"\nkey_name       = \"techiescamp\"\ninstance_count = 1\nvolume-size = 20\n\n# VPC id\nvpc_id  = \"vpc-0a5ca4a92c2e10163\"\nsubnet_ids     = [\"subnet-058a7514ba8adbb07\"]\n\n# Ec2 Tags\nname        = \"prometheus-stack\"\nowner       = \"techiescamp\"\nenvironment = \"dev\"\ncost_center = \"techiescamp-projects\"\napplication = \"monitoring\"<\/code><\/pre>\n<p>Now we can provision the AWS EC2 &amp; Security group using Terraform.<\/p>\n<pre><code>cd terraform-aws\/prometheus-stack\/\nterraform fmt\nterraform init\nterraform validate<\/code><\/pre>\n<p>Execute the plan and apply the changes.<\/p>\n<pre><code>terraform plan --var-file=..\/vars\/ec2.tfvars\nterraform apply --var-file=..\/vars\/ec2.tfvars<\/code><\/pre>\n<p>Before typing &#8216;<strong>yes<\/strong>&#8216; make sure the desired resources are being created. After running Terraform, the Output should look like the following:<\/p>\n<pre><code>Apply complete! Resources: 2 added, 0 changed, 0 destroyed.\n\nOutputs:\n\ninstance_public_dns = [\n  \"ec2-34-216-95-97.us-west-2.compute.amazonaws.com\",\n]\ninstance_public_ip = [\n  \"34.216.95.97\",\n]\ninstance_state = [\n  \"running\",\n]<\/code><\/pre>\n<p>Now we can connect to the AWS EC2 machine just created using the public IP. Replace the key path\/name and IP accordingly.<\/p>\n<pre><code>ssh -i ~\/.ssh\/techiescamp.pem ubuntu@34.216.95.97<\/code><\/pre>\n<p>We will check the <a href=\"https:\/\/devopscube.com\/ec2-user-data\/\">cloud-init logs<\/a> to see if the user data script has run successfully.<\/p>\n<pre><code>tail \/var\/log\/cloud-init-output.log<\/code><\/pre>\n<p>Below is an example output. It should show the Docker and Docker Compose versions highlighted in the image.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-42-14.png\" class=\"kg-image\" alt=\"verify user data execution via cloud init logs.\" loading=\"lazy\" width=\"666\" height=\"322\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-42-14.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-42-14.png 666w\"><\/figure>\n<p>Let&#8217;s verify the docker and docker-compose versions again.<\/p>\n<pre><code>sudo docker version\nsudo docker-compose version<\/code><\/pre>\n<p>Now that the instance is ready with the required utilities, let&#8217;s deploy the Prometheus stack using Docker Compose.<\/p>\n<h2 id=\"deploy-prometheus-stack-using-docker-compose\">Deploy Prometheus Stack Using Docker Compose<\/h2>\n<p>First, clone the project code repository to the server.<\/p>\n<pre><code>git clone https:\/\/github.com\/techiescamp\/devops-projects\ncd devops-projects\/04-prometheus-observability-stack<\/code><\/pre>\n<p>Execute the following <strong>make command<\/strong> to update the server IP in the Prometheus config file. <\/p>\n<p>We are running the node exporter on the same server to fetch the server metrics. We also update the alert manager endpoint to the server&#8217;s public IP address.<\/p>\n<pre><code>make all<\/code><\/pre>\n<p>You should see an output as shown below.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-86-10.png\" class=\"kg-image\" alt=\"makefile execution to change prometheus IP\" loading=\"lazy\" width=\"605\" height=\"731\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-86-10.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-86-10.png 605w\"><\/figure>\n<p>Bring up the stack using Docker Compose. It will deploy Prometheus, Alert Manager, Node exporter, and Grafana<\/p>\n<pre><code>sudo docker-compose up -d<\/code><\/pre>\n<p>On a successful execution, you should see the following output saying <strong><code>Running 5\/5<\/code><\/strong><\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-109-7.png\" class=\"kg-image\" alt=\"docker-compose up  for prometheus stack\" loading=\"lazy\" width=\"695\" height=\"260\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-109-7.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-109-7.png 695w\"><\/figure>\n<p>Now, with your servers IP address you can access all the apps on different ports.<\/p>\n<ol>\n<li><strong>Prometheus<\/strong>: <a href=\"http:\/\/your-ip-address:9090\/?ref=devopscube.com\">http:\/\/your-ip-address:9090<\/a><\/li>\n<li><strong>Alert Manager<\/strong>:  <a href=\"http:\/\/your-ip-address:9093\/?ref=devopscube.com\">http:\/\/your-ip-address:9093<\/a><\/li>\n<li><strong>Grafana<\/strong>: <a href=\"http:\/\/your-ip-address:3000\/?ref=devopscube.com\">http:\/\/your-ip-address:3000<\/a><\/li>\n<\/ol>\n<p>Now that the stack deployment is done, the rest of the configuration and testing will be done using the GUI.<\/p>\n<h2 id=\"validate-prometheus-node-exporter-metrics\">Validate Prometheus Node Exporter Metrics<\/h2>\n<p>If you visit <a href=\"http:\/\/your-ip-address:9090\/?ref=devopscube.com\">http:\/\/your-ip-address:9090<\/a>, you will be able to access the Prometheus dashboard as shown below.<\/p>\n<p>Validate the targets, rules, and configurations as shown below. The target would be the Node exporter URL.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/prometheus-dashbaord-1-1.gif\" class=\"kg-image\" alt=\"validating prometheus rules and targets\" loading=\"lazy\" width=\"1920\" height=\"1115\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/prometheus-dashbaord-1-1.gif 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/prometheus-dashbaord-1-1.gif 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/03\/prometheus-dashbaord-1-1.gif 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/prometheus-dashbaord-1-1.gif 1920w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Now let&#8217;s execute a promQL statement to view <strong><code>node_cpu_seconds_total<\/code><\/strong> metrics scraped from the node exporter.<\/p>\n<pre><code>avg by (instance,mode) (irate(node_cpu_seconds_total{mode!='idle'}[1m]))<\/code><\/pre>\n<p>You should be able to data in graph as shown below.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-104-6.png\" class=\"kg-image\" alt=\"executing a promQL statement to get graph\" loading=\"lazy\" width=\"815\" height=\"810\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-104-6.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-104-6.png 815w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<h2 id=\"configure-grafana-dashboards\">Configure Grafana Dashboards<\/h2>\n<p>Now, let&#8217;s configure Grafana dashboards for the Node Exporter metrics.<\/p>\n<p>Grafana can be accessed at: <a href=\"http:\/\/your-ip-address:3000\/?ref=devopscube.com\">http:\/\/your-ip-address:3000<\/a><\/p>\n<p>Use <strong>admin<\/strong>&nbsp;as the username and password to log in to Grafana.<\/p>\n<p>Now we need to add the Prometheus URL as the data source from Connections\u2192 Add new connection\u2192 Prometheus \u2192 Add new data source.<\/p>\n<p>Here is the demo.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/grafana-1.gif\" class=\"kg-image\" alt=\"Configuring Grafana Dashboards\" loading=\"lazy\" width=\"1920\" height=\"1154\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/grafana-1.gif 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/grafana-1.gif 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/03\/grafana-1.gif 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/grafana-1.gif 1920w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<h3 id=\"configure-node-exporter-dashboard\">Configure Node Exporter Dashboard<\/h3>\n<p>Grafana has many pre-built node exporter templates to give us a ready-to-use dashboard for the key node exporter metrics.<\/p>\n<p>To import a dashboard, go to Dashboards &#8211;&gt; Create Dashboard &#8211;&gt; Import Dashboard &#8211;&gt; Type 10180 and click load &#8211;&gt; Select Prometheus Data source &#8211;&gt; Import<\/p>\n<p>Here is the demo.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/grafana-dashboards-1.gif\" class=\"kg-image\" alt=\"Configuring Node Exporter Dashboard using template.\" loading=\"lazy\" width=\"1920\" height=\"1154\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/grafana-dashboards-1.gif 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/grafana-dashboards-1.gif 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/03\/grafana-dashboards-1.gif 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/grafana-dashboards-1.gif 1920w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Once the dashboard template is imported,  you should be able to see all the node exporter metrics as shown below.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-106-4.png\" class=\"kg-image\" alt=\"Node exporter Grafana dashboard.\" loading=\"lazy\" width=\"1046\" height=\"1201\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-106-4.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-106-4.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-106-4.png 1046w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<h2 id=\"simulate-test-alert-manager-alerts\">Simulate &amp; Test Alert Manager Alerts<\/h2>\n<p>You can access the Alertmanager dashboard on <a href=\"http:\/\/your-ip-address:9093\/?ref=devopscube.com\">http:\/\/your-ip-address:9093<\/a><\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-107-7.png\" class=\"kg-image\" alt=\"Alert manager dashboard\" loading=\"lazy\" width=\"731\" height=\"484\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-107-7.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-107-7.png 731w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Alert rules are already backed into the Prometheus configuration through <strong><code>alertrules.yaml<\/code><\/strong>. If you go to the alerts option in the Prometheus menu, you will be able to see the configured alerts as shown below.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-108-10.png\" class=\"kg-image\" alt=\"prometheus alert page.\" loading=\"lazy\" width=\"791\" height=\"566\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-108-10.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-108-10.png 791w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>As you can see, all the alerts are in the inactive stage. To test the alerts, we need to simulate these alerts using a few Linux utilities.<\/p>\n<p>You can also check the alert rules using the native <a href=\"https:\/\/prometheus.io\/docs\/prometheus\/latest\/command-line\/promtool\/?ref=devopscube.com\" rel=\"noreferrer noopener\">promtool<\/a> prometheus CLI. We need to run promtool command from inside the prometheus container as shown below.<\/p>\n<pre><code>sudo docker exec -it prometheus promtool check rules \/etc\/prometheus\/alertrules.yml<\/code><\/pre>\n<h3 id=\"test-high-storage-cpu-alert\">Test: High Storage &amp; CPU Alert<\/h3>\n<pre><code>dd if=\/dev\/zero of=testfile_16GB bs=1M count=16384; openssl speed -multi $(nproc --all) &amp;<\/code><\/pre>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-21-24.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"965\" height=\"616\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-21-24.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-21-24.png 965w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-22-23.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"954\" height=\"614\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-22-23.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-22-23.png 954w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Now we can check the Alert Manager UI to confirm the alerts that were fired.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-23-28.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"809\" height=\"540\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-23-28.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-23-28.png 809w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>Now let&#8217;s rollback the changes and see the fired alerts has been resolved.<\/p>\n<pre><code>rm testfile_16GB &amp;&amp; kill $(pgrep openssl)<\/code><\/pre>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-24-19.png\" class=\"kg-image\" alt=\"\" loading=\"lazy\" width=\"968\" height=\"618\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-24-19.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-24-19.png 968w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<h2 id=\"cleanup-the-setup\">Cleanup The Setup<\/h2>\n<p>To tear down the setup, execute the following Terraform command from your workstation.<\/p>\n<pre><code>terraform destroy --var-file=..\/vars\/ec2.tfvars<\/code><\/pre>\n<h2 id=\"possible-errors\">Possible Errors<\/h2>\n<p>If you don&#8217;t have the correct EC2 AMI ID set in the vars file, you will get the following error. To rectify the issue, update the correct AMI ID related to the region you are using.<\/p>\n<pre><code>Error: creating EC2 Instance: InvalidAMIID.NotFound: The image id '[ami-0a75bd84854bc95c9]' does not exist\n\u2502       status code: 400, request id: 34d38d4d-c3b8-47e6-9c27-1b1cbccbab83<\/code><\/pre>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>As a quick recap we learned to provision the AWS infra using Terraform.<\/p>\n<p>Then we brough up the Prometheus Observability stack using Docker compose and configured Grafana to create Node Exporter metrics dashboard.<\/p>\n<p>Also we simulated alerts to check the validate the alerting.<\/p>\n<p>If you&#8217;re facing any kind of issues, let me know in the comments section.<\/p>\n<p>If you are interested in Prometheus certification (PCA), check out our <a href=\"https:\/\/devopscube.com\/prometheus-certified-associate\/\" rel=\"noreferrer noopener\">Prometheus Certified Associate<\/a> exam Guide.<\/p>\n<hr>\n<p><strong>Ngu\u1ed3n:<\/strong> <a href=\"https:\/\/devopscube.com\/setup-prometheus-using-docker\/\" target=\"_blank\" rel=\"noopener noreferrer\">Setting Up Prometheus Using Docker Compose &amp; Terraform \u2014 DevOpsCube<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Source: https:\/\/devopscube.com\/setup-prometheus-using-docker\/<\/p>\n","protected":false},"author":1,"featured_media":634,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-633","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops"],"_links":{"self":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/633","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=633"}],"version-history":[{"count":0,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/633\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/media\/634"}],"wp:attachment":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=633"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=633"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=633"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}