<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Daimus Suudi</title>
    <description>The latest articles on DEV Community by Daimus Suudi (@daimus).</description>
    <link>https://dev.to/daimus</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F575100%2F778f1932-7cf7-40c5-be63-3882a3c249db.png</url>
      <title>DEV Community: Daimus Suudi</title>
      <link>https://dev.to/daimus</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/daimus"/>
    <language>en</language>
    <item>
      <title>Docker Logs Observability Using Grafana</title>
      <dc:creator>Daimus Suudi</dc:creator>
      <pubDate>Wed, 19 Mar 2025 10:58:33 +0000</pubDate>
      <link>https://dev.to/daimus/docker-logs-observability-using-grafana-3mf2</link>
      <guid>https://dev.to/daimus/docker-logs-observability-using-grafana-3mf2</guid>
      <description>&lt;p&gt;Managing logs is a developer’s responsibility—never be caught off guard when asked, “Where’s the error?” 😆 If you’re managing a single-instance container on a VPS, this article is for you. We’ll implement a simple yet effective solution that eliminates the need to log in via SSH just to check logs. With this setup, you can go beyond just viewing logs—you’ll be able to create dashboards, track metrics, perform searches, and even set up alerts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advantages of This Approach
&lt;/h2&gt;

&lt;p&gt;With this setup, you don’t have to worry about managing log files, retention, or storage on your application. Simply log to the console, and Promtail will automatically collect and send the logs to Loki. But remember, you have to follow logging best practices to maximize the benefits of this observability stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use appropriate logging levels (INFO, WARN, ERROR, etc.).&lt;/li&gt;
&lt;li&gt;Write structured and meaningful log messages.&lt;/li&gt;
&lt;li&gt;Keep logs concise, avoid excessive logging to prevent noise.&lt;/li&gt;
&lt;li&gt;Never expose sensitive information in logs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Use Grafana?
&lt;/h2&gt;

&lt;p&gt;Grafana is a powerful open-source tool for monitoring, visualizing, and analyzing logs and metrics. It allows you to turn raw log data into meaningful insights with interactive dashboards. Unlike traditional log viewing methods that require manual SSH access, Grafana provides a centralized interface to track system performance and detect anomalies in real-time.&lt;/p&gt;

&lt;p&gt;However, Grafana alone is not enough for log observability. We need a complete stack that includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Grafana: The visualization and dashboard tool that helps you explore log data and set up alerts.&lt;/li&gt;
&lt;li&gt;Loki: A log aggregation system designed for efficiency and scalability, acting as a backend for storing and indexing logs.&lt;/li&gt;
&lt;li&gt;Promtail: A lightweight log collector that ships logs from Docker containers to Loki.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All three components can run on Docker. In the next section, I’ll provide a simple Docker Compose setup to deploy them easily.&lt;/p&gt;

&lt;p&gt;But before that, you need to configure Loki and Promtail. Here is the configuration for Loki.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;auth_enabled: false

server:
  http_listen_port: 3100
  grpc_listen_port: 9096
  log_level: debug
  grpc_server_max_concurrent_streams: 1000

common:
  instance_addr: 127.0.0.1
  path_prefix: /tmp/loki
  storage:
    filesystem:
      chunks_directory: /tmp/loki/chunks
      rules_directory: /tmp/loki/rules
  replication_factor: 1
  ring:
    kvstore:
      store: inmemory

query_range:
  results_cache:
    cache:
      embedded_cache:
        enabled: true
        max_size_mb: 100

limits_config:
  metric_aggregation_enabled: true

schema_config:
  configs:
    - from: 2020-10-24
      store: tsdb
      object_store: filesystem
      schema: v13
      index:
        prefix: index_
        period: 24h

pattern_ingester:
  enabled: true
  metric_aggregation:
    loki_address: localhost:3100

ruler:
  alertmanager_url: http://localhost:9093

frontend:
  encoding: protobuf
# By default, Loki will send anonymous, but uniquely-identifiable usage and configuration
# analytics to Grafana Labs. These statistics are sent to https://stats.grafana.org/
#
# Statistics help us better understand how Loki is used, and they show us performance
# levels for most users. This helps us prioritize features and documentation.
# For more information on what's sent, look at
# https://github.com/grafana/loki/blob/main/pkg/analytics/stats.go
# Refer to the buildReport method to see what goes into a report.
#
# If you would like to disable reporting, uncomment the following lines:
#analytics:
#  reporting_enabled: false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save this configuration somewhere on your server. Next, create a Promtail configuration to collect Docker logs and send them to Loki.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://loki:3100/loki/api/v1/push

scrape_configs:
  - job_name: docker-logs
    docker_sd_configs:
      - host: unix:///var/run/docker.sock
        refresh_interval: 5s
    relabel_configs:
      - source_labels: [__meta_docker_container_name]
        target_label: container
      - source_labels: [__meta_docker_image]
        target_label: image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create the Docker Compose configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: "3.3"

networks:
  loki:

services:
  loki:
    image: grafana/loki:latest
    ports:
      - "3100:3100"
    command: -config.file=/etc/loki/local-config.yaml
    volumes:
      - ./loki-config.yml:/etc/loki/local-config.yaml
    networks:
      - loki

  promtail:
    image: grafana/promtail:latest
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./promtail-config.yml:/etc/promtail/config.yml
    command: -config.file=/etc/promtail/config.yml
    networks:
      - loki

  grafana:
    environment:
      - GF_PATHS_PROVISIONING=/etc/grafana/provisioning
      - GF_AUTH_ANONYMOUS_ENABLED=false
      - GF_FEATURE_TOGGLES_ENABLE=alertingSimplifiedRouting,alertingQueryAndExpressionsStepMode
    entrypoint:
      - sh
      - -euc
      - |
        mkdir -p /etc/grafana/provisioning/datasources
        cat &amp;lt;&amp;lt;EOF &amp;gt; /etc/grafana/provisioning/datasources/ds.yaml
        apiVersion: 1
        datasources:
        - name: Loki
          type: loki
          access: proxy
          orgId: 1
          url: http://loki:3100
          basicAuth: false
          isDefault: true
          version: 1
          editable: false
        EOF
        /run.sh
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    networks:
      - loki
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fire up all three services with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose up -d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can verify that Loki is up and running.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To view readiness, navigate to &lt;a href="http://your-server-ip:3100/ready" rel="noopener noreferrer"&gt;http://your-server-ip:3100/ready&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;To view metrics, navigate to &lt;a href="http://your-server-ip:3100/metrics" rel="noopener noreferrer"&gt;http://your-server-ip:3100/metrics&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next, you can access Grafana by opening &lt;a href="http://your-server-ip:3000" rel="noopener noreferrer"&gt;http://your-server-ip:3000&lt;/a&gt; in your browser. By default, the login credentials are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Username: admin&lt;/li&gt;
&lt;li&gt;Password: admin&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Upon your first login, Grafana will prompt you to change the password for security reasons. Once inside, you can start adding Loki as a data source and explore your logs in a more interactive way. 🚀&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Minimal Automatic Deployment Using DockerHub Webhook</title>
      <dc:creator>Daimus Suudi</dc:creator>
      <pubDate>Tue, 18 Mar 2025 08:15:27 +0000</pubDate>
      <link>https://dev.to/daimus/minimal-automatic-deployment-using-dockerhub-webhook-131b</link>
      <guid>https://dev.to/daimus/minimal-automatic-deployment-using-dockerhub-webhook-131b</guid>
      <description>&lt;p&gt;Automating deployment is crucial for streamlining the development workflow. Instead of manually deploying code every time a change is pushed to the repository, an automated deployment system ensures a seamless and efficient process.&lt;/p&gt;

&lt;p&gt;However, not all teams have access to advanced infrastructure like Kubernetes, CI/CD platforms, or expensive cloud services. Many developers rely on free repository hosting (such as GitHub and Docker Hub) and old-school VPS servers with minimal cost and resources. In such cases, a lightweight, webhook-based deployment approach provides a simple and effective solution.&lt;/p&gt;

&lt;p&gt;This tutorial covers setting up an automated deployment pipeline using Docker Hub webhooks and a webhook server, making it ideal for low-cost, minimal-resource environments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyxj3fb0wj94h81nrsjjl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyxj3fb0wj94h81nrsjjl.png" alt="Image cicd-workflow" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;PS: Building a Docker image is a separate process that can be done on your local machine or through an external CI/CD system. Once the image is built and pushed to Docker Hub, the next step is to automate its deployment. This is where webhooks come into play.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create Deployment Script
&lt;/h2&gt;

&lt;p&gt;The first step is to create a deployment script. This script will handle removing the existing container, pulling the latest image, and running the updated container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

docker stop &amp;lt;container_name&amp;gt; || true
docker rm &amp;lt;container_name&amp;gt; || true
docker pull &amp;lt;image_tag&amp;gt;
docker run -d --name &amp;lt;container_name&amp;gt; &amp;lt;image_tag&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the script in a suitable location on your server, and don’t forget to make it executable&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chmod +x deploy.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install &amp;amp; Configure Webhook
&lt;/h2&gt;

&lt;p&gt;The next step is to install and configure the webhook. I am using the webhook package from &lt;a href="https://github.com/adnanh/webhook" rel="noopener noreferrer"&gt;https://github.com/adnanh/webhook&lt;/a&gt;. First, install it using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update &amp;amp;&amp;amp; sudo apt install -y webhook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we need to create a configuration file for the webhook. This configuration defines a series of actions triggered when the webhook is called. You can also send payloads, perform validation, and more.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
  {
    "id": "deploy",
    "execute-command": "/home/admin/scripts/deploy.sh",
    "command-working-directory": "/home/admin/scripts"
  }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the configuration file on your server, then start the webhook server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;webhook -verbose -hotreload -hooks=/home/admin/webhook/hooks.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will start up on default port 9000 and will provide you with one HTTP endpoint&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://yourserver:9000/hooks/{hook_id}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By performing HTTP GET or POST request to that endpoint, your specified script would be executed.&lt;/p&gt;

&lt;p&gt;You can change the ip, port, protocol etc. Documentation is your friend 😉.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting In Docker Hub
&lt;/h2&gt;

&lt;p&gt;Next, we need to add a webhook to Docker Hub by following these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Login into your docker hub account&lt;/li&gt;
&lt;li&gt;Go to your repository&lt;/li&gt;
&lt;li&gt;Go to Webhooks tabs&lt;/li&gt;
&lt;li&gt;Insert webhook name and URL and hit (&lt;strong&gt;+&lt;/strong&gt;) icon&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Voilà! From now on, whenever a new image is pushed, Docker Hub will send a webhook to your server, triggering the deployment script automatically. 🚀&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>cicd</category>
    </item>
  </channel>
</rss>
