<?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: Ritesh Singh</title>
    <description>The latest articles on DEV Community by Ritesh Singh (@ritesh355).</description>
    <link>https://dev.to/ritesh355</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%2F3485858%2Fc86e8947-e7fa-4433-b3e8-3da407ed5dd3.png</url>
      <title>DEV Community: Ritesh Singh</title>
      <link>https://dev.to/ritesh355</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ritesh355"/>
    <language>en</language>
    <item>
      <title>🚀 AWS Multi-Region Disaster Recovery Architecture (Production-Grade)</title>
      <dc:creator>Ritesh Singh</dc:creator>
      <pubDate>Thu, 22 Jan 2026 19:23:40 +0000</pubDate>
      <link>https://dev.to/ritesh355/aws-multi-region-disaster-recovery-architecture-production-grade-4ec4</link>
      <guid>https://dev.to/ritesh355/aws-multi-region-disaster-recovery-architecture-production-grade-4ec4</guid>
      <description>&lt;h2&gt;
  
  
  📌 Overview
&lt;/h2&gt;

&lt;p&gt;In real-world systems, downtime is not an option. Cloud applications must survive instance failures, service outages, and even full regional failures.&lt;/p&gt;

&lt;p&gt;In this blog, I’ll walk you through a hands-on AWS Multi-Region Disaster Recovery (DR) architecture that automatically shifts traffic to a secondary region without manual intervention.&lt;/p&gt;

&lt;h2&gt;
  
  
  This project simulates how enterprise systems survive regional outages.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  🏗️ Architecture Diagram
&lt;/h2&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%2F4mkv6359yfnkfl6h1uzz.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%2F4mkv6359yfnkfl6h1uzz.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🔧 Architecture Components
&lt;/h3&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%2F58hoxztky3q5v6gyqkf9.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%2F58hoxztky3q5v6gyqkf9.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Primary Region (ap-south-1)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application Load Balancer (ALB)&lt;/li&gt;
&lt;li&gt;Auto Scaling Group (EC2 instances from AMI)&lt;/li&gt;
&lt;li&gt;Amazon RDS (Primary)&lt;/li&gt;
&lt;li&gt;Amazon EFS (Shared storage)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disaster Recovery Region (us-east-1)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application Load Balancer (ALB)&lt;/li&gt;
&lt;li&gt;Auto Scaling Group (EC2 from copied AMI)&lt;/li&gt;
&lt;li&gt;Amazon RDS Read Replica&lt;/li&gt;
&lt;li&gt;Amazon EFS backup / replicated data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Global Services&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Amazon Route 53 (DNS Failover &amp;amp; Health Checks)
## 🔄 Disaster Recovery Flow&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;User traffic enters through &lt;strong&gt;Amazon Route 53&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Route 53 routes traffic to &lt;strong&gt;Primary ALB (ap-south-1)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Health checks continuously monitor application health&lt;/li&gt;
&lt;li&gt;On failure detection:

&lt;ul&gt;
&lt;li&gt;Route 53 redirects traffic to &lt;strong&gt;DR ALB (us-east-1)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Auto Scaling launches EC2 instances from copied AMI&lt;/li&gt;
&lt;li&gt;RDS Read Replica is promoted to Primary&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Application becomes available from DR region &lt;strong&gt;without manual intervention&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  📂 Implementation Details
&lt;/h2&gt;

&lt;p&gt;Detailed, step-by-step implementation guides with screenshots and diagrams&lt;br&gt;
are available in the &lt;a href="//./steps"&gt;&lt;code&gt;/steps&lt;/code&gt;&lt;/a&gt; directory:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EC2 &amp;amp; AMI creation&lt;/li&gt;
&lt;li&gt;ALB &amp;amp; Auto Scaling setup&lt;/li&gt;
&lt;li&gt;Route 53 DNS failover&lt;/li&gt;
&lt;li&gt;RDS cross-region replication &amp;amp; promotion&lt;/li&gt;
&lt;li&gt;EFS backup strategy&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Step 1: EC2 &amp;amp; AMI Setup (Primary Region)
&lt;/h1&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%2F61c5yzucbqgpcamxl7lv.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%2F61c5yzucbqgpcamxl7lv.png" alt=" " width="579" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this step, we launch an EC2 instance in the primary region&lt;br&gt;
(ap-south-1) and deploy an NGINX application.&lt;/p&gt;
&lt;h2&gt;
  
  
  Objective
&lt;/h2&gt;

&lt;p&gt;Launch an EC2 instance and prepare a reusable AMI for Auto Scaling and DR.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why This Step?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;EC2 hosts the application&lt;/li&gt;
&lt;li&gt;AMI ensures consistent server configuration&lt;/li&gt;
&lt;li&gt;Enables fast recovery in another region&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Services Used
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;EC2&lt;/li&gt;
&lt;li&gt;AMI&lt;/li&gt;
&lt;li&gt;Security Groups&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Implementation Steps
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1️⃣ Launch EC2
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Region: ap-south-1&lt;/li&gt;
&lt;li&gt;AMI: Amazon Linux 2&lt;/li&gt;
&lt;li&gt;Instance type: t2.micro&lt;/li&gt;
&lt;li&gt;Security Group:

&lt;ul&gt;
&lt;li&gt;SSH (22)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  - HTTP (80)
&lt;/h2&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%2Fcs1c6xizlvoo42xgh3g7.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%2Fcs1c6xizlvoo42xgh3g7.png" alt=" " width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&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%2Fqtu2i59gziju7pkxatr6.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%2Fqtu2i59gziju7pkxatr6.png" alt=" " width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2️⃣ Install Application
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install &lt;/span&gt;nginx &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Verify Application
&lt;/h3&gt;

&lt;p&gt;Open browser&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://&amp;lt;ec2-public-ip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create AMI
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;EC2--&amp;gt; Action --&amp;gt; Create Image&lt;/li&gt;
&lt;li&gt;Name: primary-app-ami&lt;/li&gt;
&lt;/ul&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%2Fwz83ijbqsobwukspyeam.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%2Fwz83ijbqsobwukspyeam.png" alt=" " width="800" height="429"&gt;&lt;/a&gt;&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%2Fudqjokhwcybrxs9xpkhn.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%2Fudqjokhwcybrxs9xpkhn.png" alt=" " width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  OUTCOME
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Application is running &lt;/li&gt;
&lt;li&gt;AMI created for auto scalling and DR region&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Step 2: ALB &amp;amp; Auto Scaling Setup
&lt;/h1&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%2Fwzsofsuaq6151b6616z3.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%2Fwzsofsuaq6151b6616z3.png" alt=" " width="561" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Objective
&lt;/h2&gt;

&lt;p&gt;Ensure high availability and self-healing EC2 infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Step?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ALB distributes traffic&lt;/li&gt;
&lt;li&gt;Auto Scaling replaces failed instances automatically&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Services Used
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ALB&lt;/li&gt;
&lt;li&gt;Target Group&lt;/li&gt;
&lt;li&gt;Auto Scaling Group&lt;/li&gt;
&lt;li&gt;Launch Template&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Implementation Steps
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1️⃣ Create Target Group
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Type: Instance&lt;/li&gt;
&lt;li&gt;Protocol: HTTP&lt;/li&gt;
&lt;li&gt;Health check path: /
git pull --rebase origin main&lt;/li&gt;
&lt;/ul&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%2F1nvesc7kbvxj5tbn1jds.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%2F1nvesc7kbvxj5tbn1jds.png" alt=" " width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2️⃣ Create Application Load Balancer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Internet-facing&lt;/li&gt;
&lt;li&gt;Select ALL AZs (Best Practice)&lt;/li&gt;
&lt;li&gt;Attach target group&lt;/li&gt;
&lt;/ul&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%2Fs2ceag31w4pfu7dk536a.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%2Fs2ceag31w4pfu7dk536a.png" alt=" " width="800" height="440"&gt;&lt;/a&gt;&lt;br&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%2F04vadvs7h4otibg749a6.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%2F04vadvs7h4otibg749a6.png" alt=" " width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3️⃣ Create Launch Template
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use AMI from Step 1&lt;/li&gt;
&lt;li&gt;Select correct VPC Security Group&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4️⃣ Create Auto Scaling Group
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Desired: 2&lt;/li&gt;
&lt;li&gt;Min: 1&lt;/li&gt;
&lt;li&gt;Max: 4&lt;/li&gt;
&lt;li&gt;Attach ALB&lt;/li&gt;
&lt;/ul&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%2Fcxt59y0grmu4005floaa.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%2Fcxt59y0grmu4005floaa.png" alt=" " width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Outcome
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;EC2 instances auto-heal&lt;/li&gt;
&lt;li&gt;Application always available&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Step 3: Route 53 Failover Routing
&lt;/h1&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%2F6n0v9wlwuj9si2jhcb4d.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%2F6n0v9wlwuj9si2jhcb4d.png" alt=" " width="491" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Route 53 continuously monitors the health of the primary ALB&lt;br&gt;
and redirects traffic to the DR region during failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Objective
&lt;/h2&gt;

&lt;p&gt;Automatically route traffic to DR region during failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Step?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;DNS-based failover&lt;/li&gt;
&lt;li&gt;No manual intervention needed&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Services Used
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Route 53&lt;/li&gt;
&lt;li&gt;Health Checks&lt;/li&gt;
&lt;li&gt;ALB&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Implementation Steps
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1️⃣ Create Hosted Zone
&lt;/h3&gt;

&lt;p&gt;Domain:&lt;br&gt;
riteshdev.me&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%2F8uqmo1jk123bbtks6d7a.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%2F8uqmo1jk123bbtks6d7a.png" alt=" " width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2️⃣ Create Health Check
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Endpoint: Primary ALB&lt;/li&gt;
&lt;li&gt;Path: /&lt;/li&gt;
&lt;li&gt;Failure threshold: 3&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3️⃣ Create DNS Records
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Primary Record
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Routing: Failover (Primary)&lt;/li&gt;
&lt;li&gt;Alias → Primary ALB&lt;/li&gt;
&lt;li&gt;Evaluate target health: Yes&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Secondary Record
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Routing: Failover (Secondary)&lt;/li&gt;
&lt;li&gt;Alias → DR ALB&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Outcome
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Traffic shifts automatically on failure&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Step 4: RDS Disaster Recover
&lt;/h1&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%2Ffjhcvc3diycc299yzo9h.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%2Ffjhcvc3diycc299yzo9h.png" alt=" " width="689" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A cross-region read replica is maintained and promoted during&lt;br&gt;
regional failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Objective
&lt;/h2&gt;

&lt;p&gt;Protect application data using cross-region replication.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Step?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;EC2 is stateless&lt;/li&gt;
&lt;li&gt;Database must survive region failure&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Services Used
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;RDS&lt;/li&gt;
&lt;li&gt;Cross-Region Read Replica&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Implementation Steps
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1️⃣ Create Primary RDS
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Region: ap-south-1&lt;/li&gt;
&lt;li&gt;Engine: MySQL&lt;/li&gt;
&lt;li&gt;Optional: Multi-AZ&lt;/li&gt;
&lt;/ul&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%2Fy1l7rmbv05uogxvnc3n3.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%2Fy1l7rmbv05uogxvnc3n3.png" alt=" " width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2️⃣ Create Read Replica
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Region: us-east-1&lt;/li&gt;
&lt;li&gt;Continuous replication&lt;/li&gt;
&lt;/ul&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%2Fbxgv1yp0jta2x9rusr9q.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%2Fbxgv1yp0jta2x9rusr9q.png" alt=" " width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3️⃣ Promote Replica (DR Test)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;RDS → Promote read replica&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Outcome
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Near-zero data loss&lt;/li&gt;
&lt;li&gt;Production-ready DR database&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🎯 Key Objectives
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Build &lt;strong&gt;highly available infrastructure&lt;/strong&gt; across multiple Availability Zones and Regions&lt;/li&gt;
&lt;li&gt;Implement &lt;strong&gt;automatic DNS-based failover&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enable &lt;strong&gt;stateless application recovery&lt;/strong&gt; using AMIs and Auto Scaling&lt;/li&gt;
&lt;li&gt;Protect &lt;strong&gt;stateful data (RDS &amp;amp; EFS)&lt;/strong&gt; against regional failures&lt;/li&gt;
&lt;li&gt;Validate DR using &lt;strong&gt;real failure simulations&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛠️ AWS Services Used
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Services&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Compute&lt;/td&gt;
&lt;td&gt;EC2, AMI, Auto Scaling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Networking&lt;/td&gt;
&lt;td&gt;VPC, ALB, Route 53&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;EBS Snapshots, EFS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;RDS (Primary + Cross-Region Read Replica)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security&lt;/td&gt;
&lt;td&gt;IAM, Security Groups&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Monitoring&lt;/td&gt;
&lt;td&gt;Route 53 Health Checks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🌍 Regions Used
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Primary Region:&lt;/strong&gt; ap-south-1
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Disaster Recovery Region:&lt;/strong&gt; us-east-1
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📁 Project Structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws-multi-region-dr/
│
├── architecture/
│   └── dr-architecture.png
│
├── steps/
│   ├── ec2-setup.md
│   ├── alb-asg.md
│   ├── route53.md
│   └── rds-dr.md
│
├── screenshots/
│
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔄 Disaster Recovery Flow
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;User traffic enters through &lt;strong&gt;Route 53&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Primary &lt;strong&gt;Application Load Balancer (ALB)&lt;/strong&gt; serves traffic from &lt;strong&gt;ap-south-1&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Route 53 &lt;strong&gt;continuously monitors application health&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;On failure:

&lt;ul&gt;
&lt;li&gt;Traffic is &lt;strong&gt;automatically routed to the DR region&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Auto Scaling &lt;strong&gt;launches EC2 instances from the copied AMI&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RDS Read Replica is promoted&lt;/strong&gt; to primary database&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;✅ &lt;strong&gt;No manual intervention required&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 Failure Scenarios Tested
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Primary EC2 instance stopped&lt;/li&gt;
&lt;li&gt;Application (NGINX) service stopped&lt;/li&gt;
&lt;li&gt;Auto Scaling instance termination&lt;/li&gt;
&lt;li&gt;Route 53 failover validation&lt;/li&gt;
&lt;li&gt;RDS Read Replica promotion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ➡ &lt;strong&gt;Result:&lt;/strong&gt; Application remained accessible via the &lt;strong&gt;DR region&lt;/strong&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  📊 RTO &amp;amp; RPO (Design Targets)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;RTO (Recovery Time Objective)&lt;/td&gt;
&lt;td&gt;~1–2 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RPO (Recovery Point Objective)&lt;/td&gt;
&lt;td&gt;Seconds (replication lag)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  💡 Why This Project Stands Out
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Real &lt;strong&gt;production-style disaster recovery design&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Hands-on &lt;strong&gt;failure testing (not just theoretical concepts)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Clean and &lt;strong&gt;modular documentation&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Covers both &lt;strong&gt;stateless (EC2) and stateful (RDS, EFS) components&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Strong &lt;strong&gt;interview-ready cloud project&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;This project simulates how &lt;strong&gt;enterprise systems survive regional outages&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🧠 Key Learnings
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Difference between &lt;strong&gt;EC2 failover vs RDS failover&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS-based failover&lt;/strong&gt; using Route 53&lt;/li&gt;
&lt;li&gt;Importance of &lt;strong&gt;AMI-based recovery&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Cross-region replication &lt;strong&gt;trade-offs&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Auto Scaling behavior during &lt;strong&gt;instance and service failures&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚀 Future Enhancements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Infrastructure automation using &lt;strong&gt;Terraform&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;CI/CD pipeline integration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CloudWatch alarms&lt;/strong&gt; and notifications&lt;/li&gt;
&lt;li&gt;Centralized &lt;strong&gt;AWS Backup policies&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;S3 cross-region replication&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📣 About the Author
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Ritesh&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Aspiring &lt;strong&gt;Cloud &amp;amp; DevOps Engineer&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Focused on building &lt;strong&gt;resilient, scalable, and secure AWS architectures&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ For Recruiters
&lt;/h2&gt;

&lt;p&gt;This repository demonstrates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud architecture design skills&lt;/li&gt;
&lt;li&gt;Disaster recovery planning and execution&lt;/li&gt;
&lt;li&gt;Operational and troubleshooting mindset&lt;/li&gt;
&lt;li&gt;Strong technical documentation practices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📌 Please explore the **&lt;code&gt;/steps&lt;/code&gt; directory&lt;/p&gt;

</description>
      <category>aws</category>
      <category>route53</category>
      <category>devops</category>
      <category>cloud</category>
    </item>
    <item>
      <title>🔥 10+ End-to-End DevOps Projects — Docker, AWS, Jenkins, Terraform, Ansible &amp; More</title>
      <dc:creator>Ritesh Singh</dc:creator>
      <pubDate>Tue, 02 Dec 2025 13:25:27 +0000</pubDate>
      <link>https://dev.to/ritesh355/10-end-to-end-devops-projects-docker-aws-jenkins-terraform-ansible-more-9ka</link>
      <guid>https://dev.to/ritesh355/10-end-to-end-devops-projects-docker-aws-jenkins-terraform-ansible-more-9ka</guid>
      <description>&lt;h1&gt;
  
  
  🚀 My Complete DevOps Projects Collection – From Beginner to Advanced (All in One Place)
&lt;/h1&gt;

&lt;p&gt;Over the last few months, I’ve been learning DevOps deeply and building real-world projects using tools like &lt;strong&gt;Docker, Jenkins, AWS, GitHub Actions, Ansible, Terraform, Lambda, MongoDB, CloudFront, Prometheus, Grafana, and more&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To organize everything, I created a single repository called &lt;strong&gt;DevOps_Projects&lt;/strong&gt;, where I have added &lt;strong&gt;all my DevOps, Cloud, and CI/CD projects&lt;/strong&gt;, each inside its own folder.&lt;/p&gt;

&lt;p&gt;This blog is a complete guide to my journey — what I built, what tools I used, and what I learned from each project.&lt;/p&gt;

&lt;p&gt;Whether you're a beginner or someone preparing for DevOps interviews, this collection will help you understand real DevOps concepts with practical implementation.&lt;/p&gt;




&lt;h1&gt;
  
  
  🎯 Why I Created This Repository
&lt;/h1&gt;

&lt;p&gt;As a fresher, one thing became clear:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Companies don’t want just theoretical knowledge — they want proof of hands-on experience.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So instead of building random mini projects, I decided to learn DevOps properly and build &lt;strong&gt;real-world, practical, production-like projects&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This repository is the outcome of that journey.&lt;br&gt;&lt;br&gt;
And I will keep adding more advanced projects as I grow.&lt;/p&gt;




&lt;h1&gt;
  
  
  📂 What’s Inside This Repository?
&lt;/h1&gt;

&lt;p&gt;Each project has its &lt;strong&gt;own folder&lt;/strong&gt;, containing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complete project code
&lt;/li&gt;
&lt;li&gt;Dockerfiles
&lt;/li&gt;
&lt;li&gt;CI/CD workflows
&lt;/li&gt;
&lt;li&gt;Configuration files
&lt;/li&gt;
&lt;li&gt;Project-specific README
&lt;/li&gt;
&lt;li&gt;Architecture diagrams (for some projects)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Below is the complete list of projects included so far:&lt;/p&gt;




&lt;h1&gt;
  
  
  🧩 Project Overview
&lt;/h1&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;📁 PROJECT-1 — Dockerized Flask App&lt;/strong&gt; &lt;a href="https://github.com/ritesh355/DevOps_Projects/tree/main/PROJECT-1" rel="noopener noreferrer"&gt;PROJECT-1&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A beginner-friendly app containerized using Docker.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I learned:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating Dockerfiles
&lt;/li&gt;
&lt;li&gt;Building/running containers
&lt;/li&gt;
&lt;li&gt;Exposing ports
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;📁 PROJECT-2 — Node.js + MongoDB App with Docker Compose&lt;/strong&gt; &lt;a href="https://github.com/ritesh355/DevOps_Projects/tree/main/PROJECT-2" rel="noopener noreferrer"&gt;PROJECT-2&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A multi-container app using Docker Compose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Learnings:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Container networking
&lt;/li&gt;
&lt;li&gt;Volumes
&lt;/li&gt;
&lt;li&gt;Service orchestration
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;📁 PROJECT-3 — Jenkins CI/CD Pipeline with Docker &amp;amp; Node.js&lt;/strong&gt; &lt;a href="https://github.com/ritesh355/DevOps_Projects/tree/main/PROJECT-3" rel="noopener noreferrer"&gt;PROJECT-3&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Automated CI/CD workflow using Jenkins.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Learnings:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jenkinsfile stages
&lt;/li&gt;
&lt;li&gt;Automated build → test → deploy
&lt;/li&gt;
&lt;li&gt;Docker integration
&lt;/li&gt;
&lt;/ul&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%2Fn12z0wdkxsuc543350ql.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%2Fn12z0wdkxsuc543350ql.png" alt=" " width="800" height="483"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;📁 PROJECT-4 — AWS CI/CD Pipeline (Node.js → EC2)&lt;/strong&gt; &lt;a href="https://github.com/ritesh355/DevOps_Projects/tree/main/PROJECT-4" rel="noopener noreferrer"&gt;PROJECT-4&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A production-ready AWS CI/CD pipeline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AWS Services Used:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CodePipeline
&lt;/li&gt;
&lt;li&gt;CodeBuild
&lt;/li&gt;
&lt;li&gt;CodeDeploy
&lt;/li&gt;
&lt;li&gt;EC2
&lt;/li&gt;
&lt;/ul&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%2Fx71aw4ege5io5k1f0k5y.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%2Fx71aw4ege5io5k1f0k5y.png" alt=" " width="800" height="273"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;📁 PROJECT-5 — CI/CD Pipeline for Web App&lt;/strong&gt; &lt;a href="https://github.com/ritesh355/DevOps_Projects/tree/main/PROJECT-5" rel="noopener noreferrer"&gt;PROJECT-5&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A simple but complete CI/CD pipeline demonstrating core DevOps concepts.&lt;/p&gt;

&lt;h2&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%2Fzarauiw2nn2a9jgahequ.png" alt=" " width="800" height="366"&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;📁 PROJECT-6 — Static Website Hosting (S3 + CloudFront + CI/CD)&lt;/strong&gt;&lt;a href="https://github.com/ritesh355/DevOps_Projects/tree/main/PROJECT-6" rel="noopener noreferrer"&gt;PROJECT-6&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A global static website hosted on AWS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I learned:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hosting using S3
&lt;/li&gt;
&lt;li&gt;CDN with CloudFront
&lt;/li&gt;
&lt;li&gt;Automated deployment using GitHub Actions
&lt;/li&gt;
&lt;/ul&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%2Fm7jjr7155w6ac7o2xim9.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%2Fm7jjr7155w6ac7o2xim9.png" alt=" " width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;📁 PROJECT-7 — Flask + AWS DynamoDB CRUD App&lt;/strong&gt; &lt;a href="https://github.com/ritesh355/DevOps_Projects/tree/main/PROJECT-7" rel="noopener noreferrer"&gt;PROJECT-7&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A cloud backend performing CRUD operations on DynamoDB.&lt;br&gt;
&lt;strong&gt;Key Learnings:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Boto3 integration
&lt;/li&gt;
&lt;li&gt;NoSQL CRUD
&lt;/li&gt;
&lt;li&gt;Deploying Flask + AWS SDK inside Docker &lt;/li&gt;
&lt;/ul&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%2F14jeurn6jmrsnyfbawfx.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%2F14jeurn6jmrsnyfbawfx.png" alt=" " width="800" height="348"&gt;&lt;/a&gt; &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;📁 PROJECT-8 — Serverless CI/CD Pipeline&lt;/strong&gt; &lt;a href="https://github.com/ritesh355/DevOps_Projects/tree/main/PROJECT-8" rel="noopener noreferrer"&gt;PROJECT-8&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A complete serverless pipeline using AWS.&lt;br&gt;
&lt;strong&gt;AWS Services Used:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lambda
&lt;/li&gt;
&lt;li&gt;API Gateway
&lt;/li&gt;
&lt;li&gt;S3
&lt;/li&gt;
&lt;li&gt;CodePipeline
&lt;/li&gt;
&lt;li&gt;CodeBuild
&lt;/li&gt;
&lt;/ul&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%2F3sjkwdkmvus1vlnt87md.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%2F3sjkwdkmvus1vlnt87md.png" alt=" " width="800" height="388"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;📁 PROJECT-9 — Full-Stack DevOps Automation&lt;/strong&gt;&lt;a href="https://github.com/ritesh355/DevOps_Projects/tree/main/PROJECT-9" rel="noopener noreferrer"&gt;PROJECT-9&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A large-scale app combining frontend, backend, cloud, monitoring, and CI/CD.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tech Used:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next.js
&lt;/li&gt;
&lt;li&gt;Docker
&lt;/li&gt;
&lt;li&gt;GitHub Actions
&lt;/li&gt;
&lt;li&gt;AWS
&lt;/li&gt;
&lt;li&gt;Prometheus &amp;amp; Grafana
&lt;/li&gt;
&lt;li&gt;Route 53
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key Learnings:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Observability
&lt;/li&gt;
&lt;li&gt;Automation workflows
&lt;/li&gt;
&lt;li&gt;Production-like infrastructure &lt;/li&gt;
&lt;/ul&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%2Fjbhg2bsphkk2mxdrooho.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%2Fjbhg2bsphkk2mxdrooho.png" alt=" " width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;📁 PROJECT-10 — DevSecOps Pipeline&lt;/strong&gt;&lt;a href="https://github.com/ritesh355/DevOps_Projects/tree/main/PROJECT-10" rel="noopener noreferrer"&gt;PROJECT-10&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A complete DevSecOps pipeline integrating CI/CD with security checks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools Used:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jenkins
&lt;/li&gt;
&lt;li&gt;Terraform
&lt;/li&gt;
&lt;li&gt;Ansible (with Ansible Vault)
&lt;/li&gt;
&lt;li&gt;Docker
&lt;/li&gt;
&lt;li&gt;Trivy
&lt;/li&gt;
&lt;li&gt;AWS
&lt;/li&gt;
&lt;/ul&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%2Fc33372mif8u69ml9wpwa.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%2Fc33372mif8u69ml9wpwa.png" alt=" " width="800" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Learnings:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Infrastructure provisioning with Terraform
&lt;/li&gt;
&lt;li&gt;Secure configuration management
&lt;/li&gt;
&lt;li&gt;Vulnerability scanning
&lt;/li&gt;
&lt;li&gt;Secure CI/CD pipelines
&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🛠 Tech Stack Covered (So Far)
&lt;/h1&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;CI/CD&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Jenkins
&lt;/li&gt;
&lt;li&gt;GitHub Actions
&lt;/li&gt;
&lt;li&gt;AWS Developer Tools
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Containerization&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Docker
&lt;/li&gt;
&lt;li&gt;Docker Compose
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Cloud&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;AWS (EC2, Lambda, S3, CloudFront, Route53, DynamoDB)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;IaC &amp;amp; Automation&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Terraform
&lt;/li&gt;
&lt;li&gt;Ansible
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Security&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Trivy
&lt;/li&gt;
&lt;li&gt;IAM
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Monitoring&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Prometheus
&lt;/li&gt;
&lt;li&gt;Grafana
&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🔥 What’s Coming Next?
&lt;/h1&gt;

&lt;p&gt;I will continue expanding this repository with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes Projects
&lt;/li&gt;
&lt;li&gt;EKS Deployment
&lt;/li&gt;
&lt;li&gt;Helm Charts
&lt;/li&gt;
&lt;li&gt;Multi-Region Terraform Architecture
&lt;/li&gt;
&lt;li&gt;Microservices with Lambda + API Gateway
&lt;/li&gt;
&lt;li&gt;ELK / Loki Log Stack
&lt;/li&gt;
&lt;li&gt;GitOps with ArgoCD
&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🌟 Final Words
&lt;/h1&gt;

&lt;p&gt;This repository reflects my journey from beginner to someone who can design &lt;strong&gt;real-world DevOps systems&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you're also learning DevOps, this repo can help you understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real CI/CD pipelines
&lt;/li&gt;
&lt;li&gt;Docker in production
&lt;/li&gt;
&lt;li&gt;AWS workflow integration
&lt;/li&gt;
&lt;li&gt;How DevOps engineers think and solve problems
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you find it helpful, feel free to ⭐ star the repository — it motivates me to build more.&lt;/p&gt;




&lt;h2&gt;
  
  
  👨‍💻 Author
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Ritesh Singh&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://www.linkedin.com/in/ritesh-singh-092b84340/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://ritesh-devops.hashnode.dev/" rel="noopener noreferrer"&gt;Hashnode&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;💻&lt;a href="https://github.com/ritesh355/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://dev.to/ritesh355"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>aws</category>
      <category>docker</category>
      <category>cicd</category>
    </item>
    <item>
      <title>🚀AWS &amp; DevOps Project : 🚀 Building a Serverless CI/CD Pipeline with AWS Lambda, CodePipeline, and GitHub</title>
      <dc:creator>Ritesh Singh</dc:creator>
      <pubDate>Mon, 10 Nov 2025 08:00:48 +0000</pubDate>
      <link>https://dev.to/ritesh355/aws-devops-project-building-a-serverless-cicd-pipeline-with-aws-lambda-codepipeline-and-50jk</link>
      <guid>https://dev.to/ritesh355/aws-devops-project-building-a-serverless-cicd-pipeline-with-aws-lambda-codepipeline-and-50jk</guid>
      <description>&lt;h1&gt;
  
  
  🚀 Building a Serverless CI/CD Pipeline with AWS Lambda, CodePipeline, and GitHub
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Author: &lt;a href="https://dev.to/ritesh355"&gt;Ritesh&lt;/a&gt;&lt;/em&gt;  &lt;/p&gt;




&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this blog, I’ll walk you through how I built a &lt;strong&gt;fully serverless CI/CD pipeline&lt;/strong&gt; using AWS services — &lt;strong&gt;no EC2, no Jenkins, no manual intervention&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;This project automatically deploys my application to &lt;strong&gt;Amazon S3 + CloudFront&lt;/strong&gt; whenever I push code to &lt;strong&gt;GitHub&lt;/strong&gt;, leveraging &lt;strong&gt;Lambda&lt;/strong&gt;, &lt;strong&gt;API Gateway&lt;/strong&gt;, &lt;strong&gt;CodePipeline&lt;/strong&gt;, and &lt;strong&gt;CodeBuild&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;Along the way, I’ll also share the &lt;strong&gt;difficulties I faced&lt;/strong&gt; (like API Gateway setup and IAM permissions) and how I solved them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Project Goal
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“Automate code deployment from GitHub → AWS → CloudFront using only serverless services.”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&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%2Fwf14r3gc4ls0ol0s49i6.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%2Fwf14r3gc4ls0ol0s49i6.png" alt=" " width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Service used
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GitHub&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Code repository &amp;amp; webhook trigger&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;API Gateway&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Receives webhook requests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AWS Lambda&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Starts CodePipeline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AWS CodePipeline&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Automates build and deploy stages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AWS CodeBuild&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Builds and tests the application&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Amazon S3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hosts static website&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Amazon CloudFront&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Delivers the website globally&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Amazon CloudWatch&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Logs &amp;amp; monitors activity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AWS IAM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manages permissions securely&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Step-by-Step Implementation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Create and Push Code to GitHub
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create a new repository — e.g. serverless-ci-cd-pipeline.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add your frontend or simple app files (HTML/CSS/JS).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Push your code to GitHub:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"initial commit"&lt;/span&gt;
git push origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 2: Create an AWS CodePipeline
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to AWS &lt;strong&gt;CodePipeline&lt;/strong&gt; → Create pipeline&lt;/li&gt;
&lt;/ol&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%2Fpr1b971x4udlf4lr979c.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%2Fpr1b971x4udlf4lr979c.png" alt=" " width="800" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&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%2F9ngw1lk8cy1i5ljdq5wj.png" alt=" " width="800" height="406"&gt;
&lt;/h2&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%2Fufmk5ht1jw4ow4ucrl1c.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%2Fufmk5ht1jw4ow4ucrl1c.png" alt=" " width="800" height="388"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Source stage:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Provider: GitHub&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Connect your repo and branch&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Build stage:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Provider: AWS CodeBuild&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create a new CodeBuild project&lt;/p&gt;

&lt;h2&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%2Fdmm3o31bwfhuiigqp88o.png" alt=" " width="800" height="433"&gt;
&lt;/h2&gt;

&lt;h2&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%2Fy7akq6amxcdqxlomw6fg.png" alt=" " width="800" height="437"&gt;
&lt;/h2&gt;

&lt;h2&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%2F2fkaswtoj2mi67eqzvux.png" alt=" " width="800" height="434"&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Deploy stage:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&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%2F3pv9pcrv3zm5hwllxiht.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%2F3pv9pcrv3zm5hwllxiht.png" alt=" " width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Provider: Amazon S3&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select your target S3 bucket&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now your pipeline can build and deploy manually — next we’ll automate it using webhooks.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 3: Create an API Gateway Endpoint
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;strong&gt;Amazon API Gateway&lt;/strong&gt; → Create API&lt;/li&gt;
&lt;/ol&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%2Fogwge71kc0zwm5c4530c.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%2Fogwge71kc0zwm5c4530c.png" alt=" " width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Choose &lt;strong&gt;HTTP API&lt;/strong&gt; → Click Build&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Under “Integrations,” choose &lt;strong&gt;Lambda function&lt;/strong&gt; (we’ll create it in the next step).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click Create&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2F3tygkx921cpt313k61eg.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%2F3tygkx921cpt313k61eg.png" alt=" " width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Copy the Invoke URL (you’ll use this in your GitHub webhook).&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Step 4: Create AWS Lambda Function
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Go to &lt;strong&gt;Lambda → Create function&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Runtime: Python 3.9&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Function name: trigger-codepipeline&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2Fzplj0b3wse8gf9mccaw3.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%2Fzplj0b3wse8gf9mccaw3.png" alt=" " width="800" height="429"&gt;&lt;/a&gt;&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%2Fxqwbhsni8wt4kjkenggp.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%2Fxqwbhsni8wt4kjkenggp.png" alt=" " width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Paste this code:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import boto3
import json

def lambda_handler(event, context):
    pipeline_name = "your-pipeline-name"
    codepipeline = boto3.client('codepipeline')

    response = codepipeline.start_pipeline_execution(name=pipeline_name)

    return {
        'statusCode': 200,
        'body': json.dumps('Pipeline triggered successfully!')
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Go to Configuration → Permissions → Execution Role&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Attach policy: AWSCodePipelineFullAccess&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attach policy: CloudWatchLogsFullAccess&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Deploy your Lambda function.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  ✅ Now Lambda can trigger your CodePipeline programmatically.
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 5: Connect Lambda to API Gateway
&lt;/h3&gt;

&lt;p&gt;In &lt;strong&gt;API Gateway → Integrations&lt;/strong&gt;, select your Lambda function.&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%2F4fmb76g4i9hlyk6766wt.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%2F4fmb76g4i9hlyk6766wt.png" alt=" " width="800" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Deploy the API.&lt;/p&gt;

&lt;p&gt;Test it by sending a POST request using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X POST https://&amp;lt;your-api-id&amp;gt;.execute-api.us-east-1.amazonaws.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 6: Add GitHub Webhook
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to your &lt;strong&gt;GitHub Repo → Settings → Webhooks → Add Webhook&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&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%2Fiufn16u82v0wle9hsuue.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%2Fiufn16u82v0wle9hsuue.png" alt=" " width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Payload URL = &lt;strong&gt;your API Gateway Invoke URL&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Content type = application/json&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2F60173s8kvwt1k38qsnu5.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%2F60173s8kvwt1k38qsnu5.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select event: Just the push event&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;6 .Click Add Webhook&lt;/p&gt;

&lt;p&gt;Now, every time you push code to GitHub, it automatically triggers the pipeline!&lt;/p&gt;




&lt;h3&gt;
  
  
  Testing the Pipeline
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Make a small code change and push it:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add .
git commit -m "update UI"
git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Go to AWS &lt;strong&gt;CodePipeline&lt;/strong&gt;, and you’ll see the pipeline running automatically.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After a few minutes, your updated code will be deployed to &lt;strong&gt;S3&lt;/strong&gt; and available via CloudFront URL.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Common Issues I Faced (and Solved)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Issue&lt;/th&gt;
&lt;th&gt;Cause&lt;/th&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;❌ &lt;em&gt;AccessDenied in S3&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;Missing IAM permissions&lt;/td&gt;
&lt;td&gt;Attached &lt;code&gt;AmazonS3FullAccess&lt;/code&gt; to CodePipeline role&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;❌ &lt;em&gt;Lambda failed to trigger pipeline&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;No permission to start pipeline&lt;/td&gt;
&lt;td&gt;Added &lt;code&gt;AWSCodePipelineFullAccess&lt;/code&gt; policy to Lambda role&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;❌ &lt;em&gt;Webhook not triggering&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;API Gateway method not deployed&lt;/td&gt;
&lt;td&gt;Re-deployed the API after integration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;❌ &lt;em&gt;Internal server error (500)&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;JSON format mismatch&lt;/td&gt;
&lt;td&gt;Validated payload from GitHub with test event&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  Security Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use IAM least privilege roles (don’t overgrant permissions).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Always use HTTPS for API Gateway.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If using GitHub tokens, rotate them regularly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Log all actions with CloudTrail (optional).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Final Outcome
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; Fully automated, serverless CI/CD pipeline&lt;/li&gt;
&lt;li&gt;No EC2 or Jenkins — pay only for what you use&lt;/li&gt;
&lt;li&gt;Deployment happens instantly on every GitHub push&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Architecture Summary:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GitHub → API Gateway → Lambda → CodePipeline → CodeBuild → S3 → CloudFront
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key Learnings
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;How to integrate &lt;strong&gt;GitHub Webhooks&lt;/strong&gt; with &lt;strong&gt;AWS Lambda&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Event-driven DevOps design&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Secure &lt;strong&gt;IAM role&lt;/strong&gt; management&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real-world CI/CD automation using AWS native tools&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;This project helped me understand the power of &lt;strong&gt;Serverless DevOps&lt;/strong&gt; — simple, scalable, and cost-efficient.&lt;/p&gt;

&lt;p&gt;It’s a perfect real-world example of how CI/CD can be built entirely with AWS services — a valuable step in my &lt;strong&gt;DevOps learning journey&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you’re getting started in DevOps or AWS, try building this — you’ll learn &lt;strong&gt;Lambda, API Gateway, and CodePipeline&lt;/strong&gt; in action.&lt;/p&gt;




&lt;p&gt;Project Links&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/ritesh355/serverless-ci-cd-demo/settings/hooks" rel="noopener noreferrer"&gt;https://github.com/ritesh355/serverless-ci-cd-demo/settings/hooks&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📢 Connect With Me
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;💼 &lt;a href="https://linkedin.com/in/ritesh-singh-092b84340" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📝 &lt;a href="https://ritesh-devops.hashnode.dev" rel="noopener noreferrer"&gt;Hashnode Blog&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💻 &lt;a href="https://github.com/ritesh355" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>lambda</category>
      <category>cicd</category>
    </item>
    <item>
      <title>From Beginner to Pro: The Ultimate Docker Command Cheatsheet 🐳📘</title>
      <dc:creator>Ritesh Singh</dc:creator>
      <pubDate>Sun, 09 Nov 2025 09:36:37 +0000</pubDate>
      <link>https://dev.to/ritesh355/from-beginner-to-pro-the-ultimate-docker-command-cheatsheet-1gac</link>
      <guid>https://dev.to/ritesh355/from-beginner-to-pro-the-ultimate-docker-command-cheatsheet-1gac</guid>
      <description>&lt;h1&gt;
  
  
  Docker Basic Commands
&lt;/h1&gt;

&lt;p&gt;Today, we focused on mastering essential Docker housekeeping commands to manage containers, images, volumes, and perform clean-up tasks effectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Concepts Covered
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Listing running and stopped containers&lt;/li&gt;
&lt;li&gt;Removing stopped containers and unused images&lt;/li&gt;
&lt;li&gt;Managing Docker volumes&lt;/li&gt;
&lt;li&gt;Executing commands inside running containers&lt;/li&gt;
&lt;li&gt;Understanding how Docker resources accumulate over time and how to keep your environment clean&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔧 Docker Commands Practiced
&lt;/h2&gt;

&lt;h3&gt;
  
  
  CONTAINER
&lt;/h3&gt;

&lt;h4&gt;
  
  
  🔍 List Containers
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps              &lt;span class="c"&gt;# Lists only running containers&lt;/span&gt;
docker ps &lt;span class="nt"&gt;-a&lt;/span&gt;           &lt;span class="c"&gt;# Lists all containers (including stopped ones)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  🧹 Remove Containers
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;rm&lt;/span&gt; &amp;lt;container_id&amp;gt;   &lt;span class="c"&gt;# Removes a specific container by ID or name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 &lt;strong&gt;Tip&lt;/strong&gt;: Use &lt;code&gt;docker ps -a&lt;/code&gt; to find stopped containers you no longer need.&lt;/p&gt;

&lt;h4&gt;
  
  
  Create &amp;amp; Run a New Container
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &amp;lt;image_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If the image is not available locally, it’ll be downloaded from Docker Hub.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Run Container in Background
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &amp;lt;image_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Run Container with Custom Name
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; &amp;lt;container_name&amp;gt; &amp;lt;image_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  IMAGES
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📦 List Docker Images
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  🧽 Remove Docker Images
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker rmi &amp;lt;image_id&amp;gt;      &lt;span class="c"&gt;# Removes an image by its ID&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 &lt;strong&gt;Useful&lt;/strong&gt; for deleting old or unused images to free up disk space.&lt;/p&gt;

&lt;h4&gt;
  
  
  Remove Unused Images
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker image prune
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Build an Image from a Dockerfile
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; &amp;lt;image_name&amp;gt;:&amp;lt;version&amp;gt; &lt;span class="nb"&gt;.&lt;/span&gt;  &lt;span class="c"&gt;# Version is optional&lt;/span&gt;
docker build &lt;span class="nt"&gt;-t&lt;/span&gt; &amp;lt;image_name&amp;gt;:&amp;lt;version&amp;gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--no-cache&lt;/span&gt;  &lt;span class="c"&gt;# Build without cache&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Port Binding in Container
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt;&amp;lt;host_port&amp;gt;:&amp;lt;container_port&amp;gt; &amp;lt;image_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Set Environment Variables in a Container
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-e&lt;/span&gt; &amp;lt;var_name&amp;gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;var_value&amp;gt; &amp;lt;container_name&amp;gt;  &lt;span class="c"&gt;# Or &amp;lt;container_id&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Start or Stop an Existing Container
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker start|stop &amp;lt;container_name&amp;gt;  &lt;span class="c"&gt;# Or &amp;lt;container_id&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Inspect a Running Container
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker inspect &amp;lt;container_name&amp;gt;  &lt;span class="c"&gt;# Or &amp;lt;container_id&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TROUBLESHOOT
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Fetch Logs of a Container
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker logs &amp;lt;container_name&amp;gt;  &lt;span class="c"&gt;# Or &amp;lt;container_id&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Open Shell Inside Running Container
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &amp;lt;container_name&amp;gt; /bin/bash
docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &amp;lt;container_name&amp;gt; sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  DOCKER HUB
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Pull an Image from Docker Hub
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull &amp;lt;image_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Publish an Image to Docker Hub
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker push &amp;lt;username&amp;gt;/&amp;lt;image_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Login to Docker Hub
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker login &lt;span class="nt"&gt;-u&lt;/span&gt; &amp;lt;image_name&amp;gt;
&lt;span class="c"&gt;# Or&lt;/span&gt;
docker login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Use &lt;code&gt;docker logout&lt;/code&gt; to remove credentials.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Search for an Image on Docker Hub
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker search &amp;lt;image_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  VOLUME
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📋 List All Volumes
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  🆕 Create a New Named Volume
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume create &amp;lt;volume_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  ❌ Delete a Named Volume
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume &lt;span class="nb"&gt;rm&lt;/span&gt; &amp;lt;volume_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  📂 Mounting Volumes
&lt;/h4&gt;

&lt;h5&gt;
  
  
  🔗 Mount a Named Volume to a Running Container
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--volume&lt;/span&gt; &amp;lt;volume_name&amp;gt;:&amp;lt;mount_path&amp;gt;
&lt;span class="c"&gt;# Or using --mount&lt;/span&gt;
docker run &lt;span class="nt"&gt;--mount&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;volume,src&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;volume_name&amp;gt;,dst&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;mount_path&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  ❓ Mount an Anonymous Volume with Running Container
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--volume&lt;/span&gt; &amp;lt;mount_path&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  📎 Create a Bind Mount
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--volume&lt;/span&gt; &amp;lt;host_path&amp;gt;:&amp;lt;container_path&amp;gt;
&lt;span class="c"&gt;# Or using --mount&lt;/span&gt;
docker run &lt;span class="nt"&gt;--mount&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;bind&lt;/span&gt;,src&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;host_path&amp;gt;,dst&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;container_path&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  🧹 Remove Unused Local Volumes
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume prune
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;📝 &lt;strong&gt;Note&lt;/strong&gt;: Use this to remove anonymous volumes that are no longer used.&lt;/p&gt;

&lt;h3&gt;
  
  
  🌐 Docker Networks – Quick Reference
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📋 List All Networks
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker network &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  🛠️ Create a Network
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker network create &amp;lt;network_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  ❌ Remove a Network
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker network &lt;span class="nb"&gt;rm&lt;/span&gt; &amp;lt;network_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Remove All Unused Networks
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker network prune
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⚠️ &lt;strong&gt;Warning&lt;/strong&gt;: This will remove all unused networks. Ensure no containers depend on them.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 Connect with Me
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;💼 &lt;a href="https://www.linkedin.com/in/ritesh-singh-092b84340/" rel="noopener noreferrer"&gt;LinkedIn – Ritesh Singh&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💻 &lt;a href="https://github.com/ritesh355" rel="noopener noreferrer"&gt;GitHub – ritesh355&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>containers</category>
      <category>aws</category>
    </item>
    <item>
      <title>Dockerfile A to Z: A Beginner’s Guide to Writing Dockerfiles the Easy Way</title>
      <dc:creator>Ritesh Singh</dc:creator>
      <pubDate>Fri, 07 Nov 2025 12:19:17 +0000</pubDate>
      <link>https://dev.to/ritesh355/dockerfile-a-to-z-a-beginners-guide-to-writing-dockerfiles-the-easy-way-34eg</link>
      <guid>https://dev.to/ritesh355/dockerfile-a-to-z-a-beginners-guide-to-writing-dockerfiles-the-easy-way-34eg</guid>
      <description>&lt;h1&gt;
  
  
  🐳 What is a Dockerfile?
&lt;/h1&gt;

&lt;p&gt;A &lt;strong&gt;Dockerfile&lt;/strong&gt; is a 📜 plain text file with instructions to build a &lt;strong&gt;Docker image&lt;/strong&gt; — think of it as a recipe for your app’s environment. When Docker reads it, it executes each step to create a lightweight, portable image for your application. 🚀&lt;/p&gt;




&lt;h2&gt;
  
  
  📘 Dockerfile Structure: Detailed Breakdown
&lt;/h2&gt;

&lt;p&gt;Here’s how a Dockerfile works, broken down into its key components with examples and best practices. 🌟&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;FROM — Base Image&lt;/strong&gt; 🏗️
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:18&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Defines the starting point by pulling a base image from &lt;strong&gt;Docker Hub&lt;/strong&gt; (e.g., &lt;code&gt;node&lt;/code&gt;, &lt;code&gt;python&lt;/code&gt;, &lt;code&gt;ubuntu&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why use it?&lt;/strong&gt; Saves time by inheriting an existing environment (e.g., Node.js pre-installed).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;✅ Best Practice&lt;/strong&gt;: Always specify a version (e.g., &lt;code&gt;node:18&lt;/code&gt; instead of &lt;code&gt;node:latest&lt;/code&gt;) to avoid surprises from updates.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  2. &lt;strong&gt;WORKDIR — Working Directory&lt;/strong&gt; 📂
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Sets the directory for all subsequent commands. Creates &lt;code&gt;/app&lt;/code&gt; if it doesn’t exist.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why use it?&lt;/strong&gt; Keeps your code organized and simplifies file paths (no need to write &lt;code&gt;/app/server.js&lt;/code&gt; repeatedly).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;✅ Best Practice&lt;/strong&gt;: Use one &lt;code&gt;WORKDIR&lt;/code&gt; per image unless you need to switch contexts.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  3. &lt;strong&gt;COPY — Copy Files into the Image&lt;/strong&gt; 📦
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Format&lt;/strong&gt;: &lt;code&gt;COPY &amp;lt;source&amp;gt; &amp;lt;destination&amp;gt;&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Copies files from your local folder to the container’s &lt;code&gt;/app&lt;/code&gt; directory.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Example&lt;/strong&gt;:
&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;  COPY package.json /app/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Why use it?&lt;/strong&gt; Adds your app’s code or dependencies to the image.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;✅ Best Practice&lt;/strong&gt;: Use a &lt;code&gt;.dockerignore&lt;/code&gt; file to exclude unnecessary files like &lt;code&gt;node_modules&lt;/code&gt; or &lt;code&gt;.git&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  4. &lt;strong&gt;RUN — Execute Commands During Build&lt;/strong&gt; ⚙️
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Runs commands during the &lt;strong&gt;image build&lt;/strong&gt; process. Results are cached for efficiency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why use it?&lt;/strong&gt; Installs dependencies or sets up your app before it runs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;✅ Tip&lt;/strong&gt;: Combine commands for caching (e.g., &lt;code&gt;RUN apt update &amp;amp;&amp;amp; apt install -y python&lt;/code&gt;), but keep them readable.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  5. &lt;strong&gt;EXPOSE — Document the Port&lt;/strong&gt; 🌐
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Informs Docker (and users) which port the app uses inside the container.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Important&lt;/strong&gt;: This &lt;strong&gt;doesn’t publish&lt;/strong&gt; the port. Use &lt;code&gt;docker run -p&lt;/code&gt; to map ports.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:3000 my-image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Maps container’s port &lt;code&gt;3000&lt;/code&gt; to host’s port &lt;code&gt;8080&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;✅ Best Practice&lt;/strong&gt;: Always document the port your app uses.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  6. &lt;strong&gt;CMD — Default Command to Run&lt;/strong&gt; ▶️
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Shell Format&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;  CMD npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Runs via a shell. Simple but less efficient.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Exec Format&lt;/strong&gt; (recommended):
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;  CMD ["node", "index.js"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;More precise, avoids extra shell processes.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Why use it?&lt;/strong&gt; Specifies the command to launch your app when the container starts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;✅ Best Practice&lt;/strong&gt;: Use exec format and ensure only &lt;strong&gt;one&lt;/strong&gt; &lt;code&gt;CMD&lt;/code&gt; per Dockerfile (last one wins).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛠️ Sample Dockerfile: Node.js App Example
&lt;/h2&gt;

&lt;p&gt;Here’s a complete Dockerfile for a Node.js app, combining all the pieces. 🚀&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Step 1: Base image&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:18&lt;/span&gt;

&lt;span class="c"&gt;# Step 2: Set working directory&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="c"&gt;# Step 3: Copy dependency files first&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;

&lt;span class="c"&gt;# Step 4: Install dependencies&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# Step 5: Copy the rest of the app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="c"&gt;# Step 6: Expose port&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;

&lt;span class="c"&gt;# Step 7: Default command&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["node", "index.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⚡ Dockerfile Mastery Tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Layers&lt;/strong&gt; 🥞: Each instruction creates a cached layer. Order matters for efficient builds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;.dockerignore&lt;/strong&gt; 🚫: Exclude unneeded files (&lt;code&gt;node_modules&lt;/code&gt;, logs, &lt;code&gt;.git&lt;/code&gt;) to keep images lean.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Order Matters&lt;/strong&gt; 🔄: Place less-changing instructions (e.g., &lt;code&gt;COPY package.json&lt;/code&gt;) early to maximize caching.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt; 🔒: &lt;strong&gt;Never&lt;/strong&gt; hardcode passwords or secrets in Dockerfiles. Use environment variables or secrets management.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;🌈 &lt;strong&gt;Happy Dockerizing!&lt;/strong&gt; Build lightweight, reproducible images and ship your apps with confidence! 🚢&lt;/p&gt;

&lt;h1&gt;
  
  
  🛠️ General Best Practice: Three-Step Build Strategy
&lt;/h1&gt;

&lt;p&gt;This &lt;strong&gt;industry-standard&lt;/strong&gt; approach applies to nearly any language project, optimizing Docker builds for speed, efficiency, and scalability. 🚀&lt;/p&gt;




&lt;h2&gt;
  
  
  📋 Three-Step Build Strategy
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Copy Dependency Files First&lt;/strong&gt; 📦
&lt;/h3&gt;

&lt;p&gt;Dependency files change less often, so copying them first maximizes Docker’s layer caching.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Node.js&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;

&lt;span class="c"&gt;# Python&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; requirements.txt ./&lt;/span&gt;

&lt;span class="c"&gt;# Java (Maven)&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; pom.xml ./&lt;/span&gt;

&lt;span class="c"&gt;# Go&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; go.mod go.sum ./&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Why?&lt;/strong&gt; Ensures dependency installation only runs when these files change.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  2. &lt;strong&gt;Install Dependencies&lt;/strong&gt; ⚙️
&lt;/h3&gt;

&lt;p&gt;This step is time-consuming, so isolating it prevents unnecessary re-runs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Node.js&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# Python&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="c"&gt;# Java (Maven)&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;mvn dependency:resolve

&lt;span class="c"&gt;# Go&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;go mod download
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Why?&lt;/strong&gt; Caches dependencies separately, speeding up builds when only code changes.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  3. &lt;strong&gt;Copy the Rest of the Application&lt;/strong&gt; 📂
&lt;/h3&gt;

&lt;p&gt;Add source files and configurations last, as they change most frequently.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Why?&lt;/strong&gt; Isolates frequent code changes to a single layer, avoiding redundant dependency installs.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📦 Minimal Dockerfile Examples by Language
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Node.js&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:18&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["node", "app.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Python&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.11&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; requirements.txt ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 5000&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["python", "app.py"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Java (Maven)&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; maven:3.9.4-eclipse-temurin-17&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; pom.xml ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;mvn dependency:resolve
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;mvn package
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["java", "-jar", "target/app.jar"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Go (Golang)&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; golang:1.21&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; go.mod go.sum ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;go mod download
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;go build &lt;span class="nt"&gt;-o&lt;/span&gt; myapp
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["./myapp"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🎯 Why This Pattern Works
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Step&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Benefits&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Copy dependencies first&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Rarely changes, maximizes Docker layer cache for faster builds.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Install dependencies&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Avoids re-running on every rebuild, saving time and resources.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Copy app code last&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Isolates frequent code changes, preventing unnecessary dependency re-installs.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🧠 Summary
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;three-step build strategy&lt;/strong&gt; is the &lt;strong&gt;best approach&lt;/strong&gt; because it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🧱 &lt;strong&gt;Leverages Docker’s caching&lt;/strong&gt; for faster, efficient builds.&lt;/li&gt;
&lt;li&gt;⚡ &lt;strong&gt;Speeds up CI/CD pipelines&lt;/strong&gt; (Jenkins, GitHub Actions, GitLab CI).&lt;/li&gt;
&lt;li&gt;🧼 &lt;strong&gt;Keeps builds clean&lt;/strong&gt; by separating dependencies from code.&lt;/li&gt;
&lt;li&gt;📦 &lt;strong&gt;Works across all languages&lt;/strong&gt; (Node.js, Python, Java, Go, etc.).&lt;/li&gt;
&lt;li&gt;☁️ &lt;strong&gt;Scales well&lt;/strong&gt; for production-grade pipelines.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ✅ Why This Is the Best Approach
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Feature&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Why It Matters&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🧱 &lt;strong&gt;Layered Build&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Docker caches each instruction, so stable layers (e.g., &lt;code&gt;package.json&lt;/code&gt;) save time.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⚡ &lt;strong&gt;Faster Rebuilds&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Only rebuild changed layers, critical for rapid development and CI/CD.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🧼 &lt;strong&gt;Clean Separation&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Dependencies and app logic are isolated, simplifying debugging and testing.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📦 &lt;strong&gt;Language-Agnostic&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Works for Node.js, Python, Java, Go, and more — just swap the tools.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;☁️ &lt;strong&gt;CI/CD Friendly&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Optimized for tools like Jenkins, GitHub Actions, and GitLab CI that rely on caching.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  🌈 &lt;strong&gt;Build smarter, ship faster!&lt;/strong&gt; 🚢
&lt;/h2&gt;

&lt;h1&gt;
  
  
  THE BEST TABLE
&lt;/h1&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Language&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Base Image&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Dependency File(s)&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Run Command&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;CMD to Start App&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Node.js&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;node:18&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;package*.json&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;npm install&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;["node", "app.js"]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Python&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;python:3.11&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;requirements.txt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pip install -r requirements.txt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;["python", "app.py"]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Java (Maven)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;maven:3.9.4-eclipse-temurin-17&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pom.xml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mvn dependency:resolve&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;["java", "-jar", "target/app.jar"]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Go (Golang)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;golang:1.21&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;go.mod&lt;/code&gt;, &lt;code&gt;go.sum&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go mod download&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;["./myapp"]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ruby&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ruby:3.2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Gemfile&lt;/code&gt;, &lt;code&gt;Gemfile.lock&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bundle install&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;["rails", "server", "-b", "0.0.0.0"]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PHP&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;php:8.2-fpm&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;composer.json&lt;/code&gt;, &lt;code&gt;composer.lock&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;composer install&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;["php-fpm"]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;C# (.NET)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mcr.microsoft.com/dotnet/sdk:8.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;*.csproj&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;dotnet restore&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;["dotnet", "run", "--project", "app.csproj"]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  c# (.net)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM mcr.microsoft.com/dotnet/sdk:8.0
WORKDIR /app
COPY *.csproj ./
RUN dotnet restore
COPY . .
RUN dotnet build
CMD ["dotnet", "run", "--project", "app.csproj"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  PHP
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM php:8.2-fpm
WORKDIR /var/www
COPY composer.json composer.lock ./
RUN composer install
COPY . .
EXPOSE 9000
CMD ["php-fpm"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  👨‍💻 Author
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Ritesh Singh&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
🌐 &lt;a href="https://www.linkedin.com/in/ritesh-singh-092b84340/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; | 📝 &lt;a href="https://ritesh-devops.hashnode.dev/" rel="noopener noreferrer"&gt;Hashnode&lt;/a&gt; | &lt;a href="https://github.com/ritesh355/Devops-journal" rel="noopener noreferrer"&gt;GITHUB&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>dockerfile</category>
      <category>docker</category>
      <category>aws</category>
    </item>
    <item>
      <title>Ansible for Beginners: Ansible Passwordless SSH Setup on AWS EC2 (Step-by-Step for Beginners)</title>
      <dc:creator>Ritesh Singh</dc:creator>
      <pubDate>Thu, 06 Nov 2025 12:28:36 +0000</pubDate>
      <link>https://dev.to/ritesh355/ansible-for-beginners-ansible-passwordless-ssh-setup-on-aws-ec2-step-by-step-for-beginners-5gie</link>
      <guid>https://dev.to/ritesh355/ansible-for-beginners-ansible-passwordless-ssh-setup-on-aws-ec2-step-by-step-for-beginners-5gie</guid>
      <description>&lt;h1&gt;
  
  
  🧠 Ansible Setup with Passwordless SSH (Private Key Method)
&lt;/h1&gt;

&lt;p&gt;This guide walks you through a &lt;strong&gt;clean Ansible setup&lt;/strong&gt; using a dedicated &lt;code&gt;ansible&lt;/code&gt; user, passwordless sudo, and private key authentication (no password prompt).&lt;/p&gt;

&lt;p&gt;This setup allows your control node to manage multiple EC2 instances without entering passwords every time, making automation smooth and efficient. Perfect for beginners wanting hands-on practice with Ansible and AWS&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Architecture Overview
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;OS&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Control Node&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Amazon Linux&lt;/td&gt;
&lt;td&gt;Runs Ansible and manages other nodes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Managed Nodes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Amazon Linux / Ubuntu&lt;/td&gt;
&lt;td&gt;Machines managed by Ansible&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🧩 Step 1 — Create Ansible User on All Nodes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  On &lt;strong&gt;each&lt;/strong&gt; node (Control + Managed):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;adduser ansible
&lt;span class="nb"&gt;sudo &lt;/span&gt;passwd ansible
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Feysdy5hk7ubdbtiwhg30.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%2Feysdy5hk7ubdbtiwhg30.png" alt=" " width="800" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Add &lt;code&gt;ansible&lt;/code&gt; to sudoers:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;visudo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fvzc952loa7b7x5ctlzyp.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%2Fvzc952loa7b7x5ctlzyp.png" alt=" " width="800" height="241"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ansible ALL=(ALL) NOPASSWD:ALL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fn0smk8z4k4tjm12ml7vx.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%2Fn0smk8z4k4tjm12ml7vx.png" alt=" " width="800" height="433"&gt;&lt;/a&gt;&lt;br&gt;
Add this line at the end: After adding press ctrl+o then enter then ctrl+x&lt;/p&gt;

&lt;p&gt;💡 This gives passwordless sudo access to the &lt;code&gt;ansible&lt;/code&gt; user.&lt;/p&gt;


&lt;h2&gt;
  
  
  🔐 Step 2 — Configure SSH on (Managed+ controle) Nodes
&lt;/h2&gt;

&lt;p&gt;Edit &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; on &lt;strong&gt;each managed node&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;vi /etc/ssh/sshd_config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uncomment or add the following lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PermitRootLogin no
PasswordAuthentication yes
PubkeyAuthentication yes
ChallengeResponseAuthentication no
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fo53ec3rk8uta27jkoedg.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%2Fo53ec3rk8uta27jkoedg.png" alt=" " width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then restart SSH:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On &lt;strong&gt;Amazon Linux&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart sshd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fg9co2glgqphs4gnzi79y.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%2Fg9co2glgqphs4gnzi79y.png" alt=" " width="800" height="466"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On &lt;strong&gt;Ubuntu&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧰 Step 4 — Install Ansible (Control Node Only)
&lt;/h2&gt;

&lt;p&gt;On &lt;strong&gt;control node&lt;/strong&gt; (Amazon Linux):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo yum install python3-pip -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo pip3 install ansible
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ansible --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F4c06s8kbwj35uty7q70c.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%2F4c06s8kbwj35uty7q70c.png" alt=" " width="800" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ansible &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fqt291jq8rd5kuxh36k07.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%2Fqt291jq8rd5kuxh36k07.png" alt=" " width="800" height="442"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🔑 Step 5 — Generate SSH Key Pair on Control Node
&lt;/h2&gt;

&lt;p&gt;Switch to &lt;code&gt;ansible&lt;/code&gt; user on &lt;strong&gt;control node&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;su - ansible
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate SSH keys:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; rsa &lt;span class="nt"&gt;-b&lt;/span&gt; 2048
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fi11fjf1c15bbrcc8lkmp.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%2Fi11fjf1c15bbrcc8lkmp.png" alt=" " width="800" height="435"&gt;&lt;/a&gt;&lt;br&gt;
Press &lt;strong&gt;Enter&lt;/strong&gt; for all prompts to accept defaults (no passphrase).&lt;/p&gt;

&lt;p&gt;You’ll get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/home/ansible/.ssh/id_rsa      (private key)
 /home/ansible/.ssh/id_rsa.pub  (public key)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&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%2Fptuvzggkw8mjj2jyl5r3.png" alt=" " width="800" height="505"&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  📤 Step 6 — Copy SSH Key to Managed Nodes (Passwordless Setup)
&lt;/h2&gt;

&lt;p&gt;Use this command on the &lt;strong&gt;control node&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-copy-id ansible@&amp;lt;managed_node_private_ip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F9f9crc9bu88hx4uvyw69.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%2F9f9crc9bu88hx4uvyw69.png" alt=" " width="800" height="413"&gt;&lt;/a&gt;&lt;br&gt;
You’ll enter the password of the &lt;code&gt;ansible&lt;/code&gt; user &lt;strong&gt;only once&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Repeat for each managed node.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-copy-id ansible@172.31.29.148
ssh-copy-id ansible@172.31.18.225
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Now test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh ansible@172.31.29.148
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fy84le98bz4pk0yewg3a5.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%2Fy84le98bz4pk0yewg3a5.png" alt=" " width="800" height="427"&gt;&lt;/a&gt;&lt;br&gt;
If it logs in &lt;strong&gt;without asking password&lt;/strong&gt;, passwordless SSH is working perfectly.&lt;/p&gt;


&lt;h2&gt;
  
  
  🧭 Step 7 — Verify Setup with Ansible Ping
&lt;/h2&gt;

&lt;p&gt;Create an inventory file &lt;code&gt;/home/ansible/hosts&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;use this command under &lt;strong&gt;/home/ansible&lt;/strong&gt; directory&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo vi hosts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fp7bbtzhces4lkskgx6tz.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%2Fp7bbtzhces4lkskgx6tz.png" alt=" " width="800" height="351"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[web]
172.31.29.148 

[dev]
172.31.18.225 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fkja926uvecq28sd8w3rj.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%2Fkja926uvecq28sd8w3rj.png" alt=" " width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now test connection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ansible all &lt;span class="nt"&gt;-i&lt;/span&gt; hosts &lt;span class="nt"&gt;-m&lt;/span&gt; ping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fi0p0j54x4gvcv2llopes.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%2Fi0p0j54x4gvcv2llopes.png" alt=" " width="800" height="422"&gt;&lt;/a&gt;&lt;br&gt;
Expected output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;172.31.29.148 | SUCCESS &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"changed"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
    &lt;span class="s2"&gt;"ping"&lt;/span&gt;: &lt;span class="s2"&gt;"pong"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
172.31.18.225 | SUCCESS &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"changed"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;,
    &lt;span class="s2"&gt;"ping"&lt;/span&gt;: &lt;span class="s2"&gt;"pong"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;









&lt;h2&gt;
  
  
  ✅ Verification Checklist
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;ansible&lt;/code&gt; user exists on all nodes&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Passwordless sudo enabled&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSH passwordless login (private key) works&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; updated and SSH restarted&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ansible ping successful&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🧩 Bonus Tip — Test with Ad Hoc Command
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ansible all &lt;span class="nt"&gt;-i&lt;/span&gt; hosts &lt;span class="nt"&gt;-m&lt;/span&gt; shell &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"hostname"&lt;/span&gt;
ansible all &lt;span class="nt"&gt;-i&lt;/span&gt; hosts &lt;span class="nt"&gt;-m&lt;/span&gt; shell &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"uptime"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see hostnames and uptime output — congratulations 🎉&lt;br&gt;
Your &lt;strong&gt;Ansible setup with private key passwordless access&lt;/strong&gt; is ready!&lt;/p&gt;




&lt;h2&gt;
  
  
  🧾 Notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Private key (&lt;code&gt;id_rsa&lt;/code&gt;) always stays on the &lt;strong&gt;control node&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Public key (&lt;code&gt;id_rsa.pub&lt;/code&gt;) is copied to managed nodes’ &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Never share or upload your private key to any other system...&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ❤️ Follow My DevOps Journey
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Ritesh Singh&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
🌐 &lt;a href="https://www.linkedin.com/in/ritesh-singh-092b84340/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; | 📝 &lt;a href="https://ritesh-devops.hashnode.dev/" rel="noopener noreferrer"&gt;Hashnode&lt;/a&gt; | &lt;a href="https://github.com/ritesh355/Devops-journal" rel="noopener noreferrer"&gt;GITHUB&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ansible</category>
      <category>aws</category>
      <category>devops</category>
      <category>ssh</category>
    </item>
    <item>
      <title>🌐DevOps and Cloud Project: Static Website Hosting with AWS S3 + CloudFront + CI/CD</title>
      <dc:creator>Ritesh Singh</dc:creator>
      <pubDate>Thu, 06 Nov 2025 05:48:26 +0000</pubDate>
      <link>https://dev.to/ritesh355/devops-and-cloud-project-static-website-hosting-with-aws-s3-cloudfront-cicd-5hhe</link>
      <guid>https://dev.to/ritesh355/devops-and-cloud-project-static-website-hosting-with-aws-s3-cloudfront-cicd-5hhe</guid>
      <description>&lt;h3&gt;
  
  
  PROJECT OVERVIEW
&lt;/h3&gt;

&lt;p&gt;This project demonstrates how to host a &lt;strong&gt;static website&lt;/strong&gt; on &lt;strong&gt;Amazon S3&lt;/strong&gt;, deliver it globally with &lt;strong&gt;CloudFront CDN&lt;/strong&gt;, and automate deployments using &lt;strong&gt;GitHub Actions&lt;/strong&gt;.  &lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;✅ Static website hosting on &lt;strong&gt;Amazon S3&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;CloudFront CDN&lt;/strong&gt; for global fast delivery + HTTPS
&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;CI/CD pipeline with GitHub Actions&lt;/strong&gt; (auto-deploy on push)
&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Cache invalidation&lt;/strong&gt; so updates are live instantly
&lt;/li&gt;
&lt;li&gt;✅ Secure &lt;strong&gt;Origin Access Control (OAC)&lt;/strong&gt; → S3 is private, only CloudFront can access
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🏗️ Architecture Workflow
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🔹 Request Flow
&lt;/h3&gt;

&lt;p&gt;User → CloudFront (Edge Cache) → [If cache miss] → S3 Bucket → CloudFront → User&lt;/p&gt;

&lt;h3&gt;
  
  
  🔹 Deployment Flow
&lt;/h3&gt;

&lt;p&gt;Developer → GitHub Repo → GitHub Actions → S3 Bucket → CloudFront → End User&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ Setup Instructions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1️⃣ Create S3 Bucket
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;strong&gt;AWS S3 Console&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Create a bucket (region example: &lt;code&gt;ap-south-1&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;Keep &lt;strong&gt;Block Public Access = ON&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Upload your static website files (&lt;code&gt;index.html&lt;/code&gt;, CSS, JS, images, etc.)&lt;/li&gt;
&lt;/ul&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%2Foxcwx4nmkgkva0v3ttc7.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%2Foxcwx4nmkgkva0v3ttc7.png" alt=" " width="800" height="410"&gt;&lt;/a&gt;&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%2Fdvctwzxcz4szyy8qd9e8.jpg" 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%2Fdvctwzxcz4szyy8qd9e8.jpg" alt=" " width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  2️⃣ Create CloudFront Distribution
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Open &lt;strong&gt;CloudFront Console&lt;/strong&gt; → Create Distribution
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Origin&lt;/strong&gt; = your S3 bucket
&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;Origin Access Control (OAC)&lt;/strong&gt; (so only CloudFront can read from S3)
&lt;/li&gt;
&lt;li&gt;Copy the CloudFront domain (e.g., &lt;code&gt;d1234abcd.cloudfront.net&lt;/code&gt;)
&lt;/li&gt;
&lt;/ul&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%2Fb8foavmywzy0rcpx5guo.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%2Fb8foavmywzy0rcpx5guo.png" alt=" " width="800" height="426"&gt;&lt;/a&gt;&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%2Fspq6x1r1923lvvx3dfhj.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%2Fspq6x1r1923lvvx3dfhj.png" alt=" " width="800" height="422"&gt;&lt;/a&gt;&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%2Fj7p8i53nv12c743ai7dj.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%2Fj7p8i53nv12c743ai7dj.png" alt=" " width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  3️⃣ Configure GitHub Actions
&lt;/h3&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%2Fllj0xomkw8r1aho67rox.jpg" 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%2Fllj0xomkw8r1aho67rox.jpg" alt=" " width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🔑 Secrets Setup in GitHub
&lt;/h3&gt;

&lt;p&gt;Go to GitHub Repo → Settings → Secrets and variables → Actions → New repository secret&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%2Ffyjia8y1lz934heeuivq.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%2Ffyjia8y1lz934heeuivq.png" alt=" " width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;AWS_ACCESS_KEY_ID&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AWS_SECRET_ACCESS_KEY&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🌍 Access Your Website
&lt;/h3&gt;

&lt;p&gt;Default →  (your CloudFront domain)&lt;/p&gt;

&lt;p&gt;Optional → Add Route 53 + ACM SSL to use a custom domain &lt;/p&gt;

&lt;h3&gt;
  
  
  📌 Future Improvements
&lt;/h3&gt;

&lt;p&gt;Add CloudWatch monitoring &amp;amp; logging&lt;/p&gt;

&lt;p&gt;Add Route 53 + SSL certificate for a custom domain&lt;/p&gt;

&lt;p&gt;Extend pipeline with tests before deployment&lt;/p&gt;

&lt;h3&gt;
  
  
  🏆 Learning Outcome
&lt;/h3&gt;

&lt;p&gt;By completing this project, I learned:&lt;/p&gt;

&lt;p&gt;How to use AWS S3 for static hosting&lt;/p&gt;

&lt;p&gt;How CloudFront works as a CDN with OAC&lt;/p&gt;

&lt;p&gt;How to build a CI/CD pipeline with GitHub Actions&lt;/p&gt;

&lt;p&gt;How to automate deployments and cache invalidations&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;🔗 Keywords:&lt;/strong&gt; AWS, S3, CloudFront, GitHub Actions, CI/CD, DevOps, Cloud&lt;br&gt;
🚀&lt;a href="https://github.com/ritesh355/aws-projects/tree/main/11-static-website-hosting-s3-cloudfront" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;⚡ Now, every time I push code to GitHub, my website auto-deploys to AWS with CloudFront CDN &lt;code&gt;🚀&lt;/code&gt;&lt;/p&gt;

</description>
      <category>cicd</category>
      <category>aws</category>
      <category>staticwebsitehosting</category>
      <category>devops</category>
    </item>
    <item>
      <title>AWS CI/CD Node.js Application using AWS CodePipeline, CodeBuild and CodeDeploy</title>
      <dc:creator>Ritesh Singh</dc:creator>
      <pubDate>Tue, 28 Oct 2025 14:57:16 +0000</pubDate>
      <link>https://dev.to/ritesh355/aws-cicd-nodejs-application-using-aws-codepipeline-codebuild-and-codedeploy-1p5j</link>
      <guid>https://dev.to/ritesh355/aws-cicd-nodejs-application-using-aws-codepipeline-codebuild-and-codedeploy-1p5j</guid>
      <description>&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%2Fwc5878f4d84j1o48nh91.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%2Fwc5878f4d84j1o48nh91.png" alt=" " width="800" height="273"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Welcome to the &lt;strong&gt;AWS CI/CD Node.js Application&lt;/strong&gt; repository! This project showcases a production-ready Node.js application deployed on AWS EC2 using a fully automated CI/CD pipeline with AWS CodePipeline, CodeBuild, and CodeDeploy. Integrated with GitHub for seamless source control, this pipeline automates building and deploying the application.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Project Overview
&lt;/h2&gt;

&lt;p&gt;This repository hosts a Node.js application (&lt;code&gt;my-app&lt;/code&gt;) that serves a "Hello from AWS CI/CD!" message on port 3000. Deployed on an AWS EC2 instance (&lt;code&gt;ip-172-31-19-118&lt;/code&gt;), it leverages a robust CI/CD pipeline to demonstrate modern DevOps practices and cloud infrastructure management.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Showcase expertise in building, testing, and deploying a Node.js application using AWS services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technologies&lt;/strong&gt;: Node.js, AWS CodePipeline, CodeBuild, CodeDeploy, EC2, GitHub.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key Achievement&lt;/strong&gt;: Resolved deployment issues (e.g., &lt;code&gt;ScriptFailed&lt;/code&gt; error with &lt;code&gt;EACCES&lt;/code&gt; permissions) to achieve a stable, automated pipeline.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛠️ Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Node.js Application&lt;/strong&gt;: Lightweight Express.js server running on port 3000.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated CI/CD Pipeline&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Source&lt;/strong&gt;: GitHub repository (&lt;code&gt;ritesh/my-aws-cicd-app&lt;/code&gt;, &lt;code&gt;main&lt;/code&gt; branch).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build&lt;/strong&gt;: AWS CodeBuild generates &lt;code&gt;build-artifact.zip&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy&lt;/strong&gt;: AWS CodeDeploy deploys to EC2 (&lt;code&gt;MyAppDeploy&lt;/code&gt;, &lt;code&gt;ProductionGroup&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Error Handling&lt;/strong&gt;: Fixed permissions issues with &lt;code&gt;npm install&lt;/code&gt; by optimizing &lt;code&gt;buildspec.yml&lt;/code&gt; and &lt;code&gt;install_deps.sh&lt;/code&gt;.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Scalability&lt;/strong&gt;: Ready for scaling with additional EC2 instances or load balancers.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Monitoring&lt;/strong&gt;: Application logs (&lt;code&gt;app.log&lt;/code&gt;) for debugging and verification.&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  📁 Repository Structure
&lt;/h2&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%2F9n4ghlrfslwlqan84f5o.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%2F9n4ghlrfslwlqan84f5o.png" alt=" " width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🛠️ Setup and Deployment
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AWS Account&lt;/strong&gt;: Permissions for CodePipeline, CodeBuild, CodeDeploy, EC2, and S3.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Account&lt;/strong&gt;: Repository &lt;code&gt;ritesh/my-aws-cicd-app&lt;/code&gt; with push access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node.js&lt;/strong&gt;: Version 20.19.5 (with npm 10.8.2).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - &lt;strong&gt;EC2 Instance&lt;/strong&gt;: Ubuntu with CodeDeploy agent installed.
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Local Setup
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Clone the Repository&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git clone https://github.com/ritesh/my-aws-cicd-app.git
   &lt;span class="nb"&gt;cd &lt;/span&gt;my-aws-cicd-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install dependencies&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run Locally:&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   node index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Access at &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  AWS CI/CD Pipeline Setup
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Step 1: Create the S3 Bucket for Artifacts
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws s3 mb s3://myapp-cicd-artifacts-123 &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/ritesh355/aws-projects/tree/main/02-s3-bucket" rel="noopener noreferrer"&gt;how to create s3 bucket CLICK&lt;/a&gt;&lt;br&gt;
This bucket stores build-artifact.zip generated by CodeBuild.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2: Launch EC2 Instance &amp;amp; Install CodeDeploy Agent
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Launch EC2&lt;/strong&gt; (Ubuntu 22.04, t3.micro, &lt;code&gt;us-east-1&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security Group&lt;/strong&gt;: Allow inbound:

&lt;ul&gt;
&lt;li&gt;SSH (22)&lt;/li&gt;
&lt;li&gt;HTTP (3000)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://github.com/ritesh355/aws-projects/tree/main/01-ec2-instance" rel="noopener noreferrer"&gt;CLICK-HERE&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install CodeDeploy Agent&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;ruby wget &lt;span class="nt"&gt;-y&lt;/span&gt;
wget https://aws-codedeploy-us-east-1.s3.amazonaws.com/latest/install
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x &lt;span class="nb"&gt;install
sudo&lt;/span&gt; ./install auto
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status codedeploy-agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Tip&lt;/strong&gt;: Verify agent is running: sudo systemctl status codedeploy-agent&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 3: Create IAM Roles
&lt;/h2&gt;

&lt;p&gt;IAM roles are &lt;strong&gt;critical&lt;/strong&gt; for secure communication between AWS services. Below are the &lt;strong&gt;four roles&lt;/strong&gt; created with &lt;strong&gt;trust policies&lt;/strong&gt; and &lt;strong&gt;permissions&lt;/strong&gt;.&lt;/p&gt;


&lt;h3&gt;
  
  
  1. EC2 Instance Role (&lt;code&gt;EC2CodeDeployRole&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: Allows EC2 to download artifacts from S3 and communicate with CodeDeploy.&lt;/p&gt;
&lt;h4&gt;
  
  
  Trust Policy
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Principal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"Service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ec2.amazonaws.com"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sts:AssumeRole"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Attached Policies&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AmazonS3ReadOnlyAccess → To download build-artifact.zip&lt;/li&gt;
&lt;li&gt;AWSCodeDeployRole → For CodeDeploy operations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Attach this role to your EC2 instance via AWS Console → EC2 → Actions → Security → Modify IAM role.&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%2Fpcjx3miyjepx0noxdiou.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%2Fpcjx3miyjepx0noxdiou.png" alt=" " width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  2. CodeBuild Service Role (CodeBuildServiceRole)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: Allows CodeBuild to read source, write artifacts to S3, and log.&lt;/p&gt;
&lt;h4&gt;
  
  
  Trust Policy
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Principal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"Service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"codebuild.amazonaws.com"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sts:AssumeRole"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Attached Policies&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWSCodeBuildAdminAccess&lt;/li&gt;
&lt;li&gt;AmazonS3FullAccess → Required to upload build-artifact.zip to s3://myapp-cicd-artifacts-123&lt;/li&gt;
&lt;/ul&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%2F8rhfsmsjufh77l1bnp0p.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%2F8rhfsmsjufh77l1bnp0p.png" alt=" " width="800" height="442"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  3. CodeDeploy Service Role (CodeDeployServiceRole)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: Allows CodeDeploy to manage deployments on EC2.&lt;/p&gt;
&lt;h4&gt;
  
  
  Trust Policy
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Principal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"Service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"codedeploy.amazonaws.com"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sts:AssumeRole"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;&lt;em&gt;Attached Policy&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AWSCodeDeployRole → Predefined AWS managed policy&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%2Fn5e3h4l92grt9c4f9oiv.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%2Fn5e3h4l92grt9c4f9oiv.png" alt=" " width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  4. CodePipeline Service Role (CodePipelineServiceRole)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: Orchestrates Source, Build, and Deploy stages.&lt;/p&gt;
&lt;h4&gt;
  
  
  Trust Policy
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Principal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"Service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"codepipeline.amazonaws.com"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sts:AssumeRole"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Attached Policies&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWSCodePipelineFullAccess&lt;/li&gt;
&lt;li&gt;AWSCodeBuildAdminAccess&lt;/li&gt;
&lt;li&gt;AWSCodeDeployFullAccess&lt;/li&gt;
&lt;li&gt;AmazonS3FullAccess
&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%2F0y7xbhvf1uniy14jovyk.png" alt=" " width="800" height="440"&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Step 4: GitHub Repository Setup
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init
git remote add origin https://github.com/ritesh/my-aws-cicd-app.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F1btpm33mkarug2e3rn8e.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%2F1btpm33mkarug2e3rn8e.png" alt=" " width="800" height="391"&gt;&lt;/a&gt;&lt;br&gt;
.gitignore:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node_modules/
package-lock.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why? Prevents EACCES errors by excluding locked files from artifacts.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 5: buildspec.yml — Build Configuration
&lt;/h3&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%2Fj544vkokshi52dukj7nh.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%2Fj544vkokshi52dukj7nh.png" alt=" " width="800" height="435"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.2&lt;/span&gt;
&lt;span class="na"&gt;phases&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runtime-versions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;nodejs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;18&lt;/span&gt;
    &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "Build completed"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;rm -rf node_modules package-lock.json&lt;/span&gt;
&lt;span class="na"&gt;artifacts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;files&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;appspec.yml&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;index.js&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;package.json&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;scripts/**/*&lt;/span&gt;
  &lt;span class="na"&gt;discard-paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;no&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Critical Fix&lt;/strong&gt;: rm -rf node_modules package-lock.json avoids permission conflicts.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 6: appspec.yml — Deployment Steps
&lt;/h3&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%2Fjn9o28du0pvxw87ah30i.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%2Fjn9o28du0pvxw87ah30i.png" alt=" " width="800" height="449"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.1&lt;/span&gt;
&lt;span class="na"&gt;os&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux&lt;/span&gt;
&lt;span class="na"&gt;files&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
    &lt;span class="na"&gt;destination&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/home/ubuntu/my-app&lt;/span&gt;
&lt;span class="na"&gt;hooks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;AfterInstall&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;scripts/install_deps.sh&lt;/span&gt;
      &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;300&lt;/span&gt;
      &lt;span class="na"&gt;runas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Runs install_deps.sh as ubuntu user to avoid root permission issues.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 7: scripts/install_deps.sh — Fix Permissions
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; /home/ubuntu/my-app
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; node_modules package-lock.json
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--cache&lt;/span&gt; /home/ubuntu/.npm &lt;span class="nt"&gt;--no-audit&lt;/span&gt;
&lt;span class="nb"&gt;chmod&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; u+w node_modules package-lock.json 2&amp;gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Key Fixes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clears old node_modules&lt;/li&gt;
&lt;li&gt;Uses custom npm cache&lt;/li&gt;
&lt;li&gt;Fixes write permissions&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Step 8: AWS CodeBuild Project (MyAppBuild)
&lt;/h3&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%2Fu371wqakrxt28r7at21q.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%2Fu371wqakrxt28r7at21q.png" alt=" " width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Source&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GitHub (&lt;code&gt;ritesh/my-aws-cicd-app&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Environment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ubuntu, Node.js 18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Buildspec&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;buildspec.yml&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Artifact&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;S3 → &lt;code&gt;myapp-cicd-artifacts-123&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Service Role&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CodeBuildServiceRole&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  Step 9: AWS CodeDeploy Application (MyAppDeploy)
&lt;/h3&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%2Fb9xpyu6sfa8q0xy7wyxn.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%2Fb9xpyu6sfa8q0xy7wyxn.png" alt=" " width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Application Name&lt;/strong&gt;: MyAppDeploy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compute Platform&lt;/strong&gt;: EC2/On-Premises&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment Group&lt;/strong&gt;: ProductionGroup

&lt;ul&gt;
&lt;li&gt;Tag: Name=MyAppServer&lt;/li&gt;
&lt;li&gt;Instance: ip-172-31-19-118&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Service Role&lt;/strong&gt;: CodeDeployServiceRole&lt;/li&gt;

&lt;/ul&gt;




&lt;h3&gt;
  
  
  step 10 AWS CodePipeline (&lt;code&gt;MyAppPipeline&lt;/code&gt;)
&lt;/h3&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%2Fltzle9a2y8ovzykqku7q.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%2Fltzle9a2y8ovzykqku7q.png" alt=" " width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Stage&lt;/th&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Configuration&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Source&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GitHub (v2)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;MyAppGitHubConnection&lt;/code&gt;, &lt;code&gt;main&lt;/code&gt; branch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Build&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;CodeBuild&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MyAppBuild&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deploy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;CodeDeploy&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;MyAppDeploy&lt;/code&gt;, &lt;code&gt;ProductionGroup&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h1&gt;
  
  
  🐞 Troubleshooting
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Common Issue:
&lt;/h2&gt;

&lt;p&gt;ScriptFailed error (exit code 243) due to EACCES permissions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution:
&lt;/h2&gt;

&lt;p&gt;Ensured &lt;code&gt;buildspec.yml&lt;/code&gt; excludes &lt;code&gt;node_modules/&lt;/code&gt; and &lt;code&gt;package-lock.json&lt;/code&gt;; &lt;code&gt;install_deps.sh&lt;/code&gt; clears residuals and sets permissions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Logs:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bash &lt;span class="nb"&gt;sudo tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 100 /var/log/aws/codedeploy-agent/codedeploy-agent.log
&lt;span class="nb"&gt;cat&lt;/span&gt; /home/ubuntu/.npm/_logs/&lt;span class="k"&gt;*&lt;/span&gt;.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Why This Project Stands Out
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DevOps Expertise:&lt;/strong&gt; End-to-end CI/CD pipeline with AWS services.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Problem-Solving:&lt;/strong&gt; Resolved complex permissions issues (EACCES on &lt;code&gt;node_modules/.package-lock.json&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automation:&lt;/strong&gt; Fully automated deployments with GitHub webhooks.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean Code:&lt;/strong&gt; Well-structured repository with clear configurations.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  📬 Contact
&lt;/h1&gt;

&lt;h2&gt;
  
  
  👨‍💻 Author
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Ritesh Singh&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://www.linkedin.com/in/ritesh-singh-092b84340/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; &lt;br&gt;
|&lt;br&gt;
📝 &lt;a href="https://ritesh-devops.hashnode.dev/" rel="noopener noreferrer"&gt;Hashnode&lt;/a&gt; &lt;br&gt;
|&lt;br&gt;
💻&lt;a href="https://github.com/ritesh355/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feel free to explore, fork, or contribute to this project! 🚀&lt;/p&gt;

</description>
      <category>cicd</category>
      <category>awscodebuild</category>
      <category>awspipeline</category>
      <category>awscodedeploy</category>
    </item>
    <item>
      <title>DevSecOps Pipeline | Jenkins, Terraform, Docker, Trivy, AWS</title>
      <dc:creator>Ritesh Singh</dc:creator>
      <pubDate>Sun, 19 Oct 2025 07:10:45 +0000</pubDate>
      <link>https://dev.to/ritesh355/devsecops-pipeline-jenkins-terraform-docker-trivy-aws-3ien</link>
      <guid>https://dev.to/ritesh355/devsecops-pipeline-jenkins-terraform-docker-trivy-aws-3ien</guid>
      <description>&lt;h1&gt;
  
  
  DevSecOps CI/CD Project
&lt;/h1&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%2Fa5wb8v9vftlj313paomm.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%2Fa5wb8v9vftlj313paomm.png" alt=" " width="800" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Project goal:&lt;/strong&gt; Build a full DevSecOps pipeline that builds, scans, pushes and deploys a Flask app using Docker, stores images in AWS ECR, provisions infrastructure with Terraform, configures servers with Ansible, secures pipeline with Trivy &amp;amp; Ansible Vault, and monitors with Prometheus + Grafana. This README documents everything you used and every step needed to reproduce, maintain and secure the workflow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Project overview &amp;amp; architecture&lt;/li&gt;
&lt;li&gt;Folder structure (recommended)&lt;/li&gt;
&lt;li&gt;Prerequisites (local &amp;amp; cloud)&lt;/li&gt;
&lt;li&gt;Terraform — provision EC2 + IAM + security groups (step-by-step)&lt;/li&gt;
&lt;li&gt;Ansible — configure servers &amp;amp; deploy containers (roles &amp;amp; playbooks)&lt;/li&gt;
&lt;li&gt;Jenkins pipeline — build, scan, push, deploy (Jenkinsfile)&lt;/li&gt;
&lt;li&gt;Security: Trivy, SonarQube (optional), Ansible Vault, Jenkins credentials, IAM least privilege&lt;/li&gt;
&lt;li&gt;Monitoring: Prometheus + Grafana + Node Exporter + Jenkins metrics plugin&lt;/li&gt;
&lt;li&gt;Correct workflow (step-by-step) + mermaid diagram for workflow image&lt;/li&gt;
&lt;li&gt;Troubleshooting &amp;amp; common pitfalls&lt;/li&gt;
&lt;li&gt;Useful commands &amp;amp; snippets&lt;/li&gt;
&lt;li&gt;Next improvements &amp;amp; checklist&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1 — Project overview &amp;amp; architecture
&lt;/h2&gt;

&lt;p&gt;High-level components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: source repo (your app + infra + ansible)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jenkins&lt;/strong&gt;: CI server (build image, run security scans, push to ECR, trigger Ansible deploy)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker&lt;/strong&gt;: containerize Flask app&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS ECR&lt;/strong&gt;: Docker registry for images&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terraform&lt;/strong&gt;: create EC2 instances, security groups, IAM roles/profiles&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ansible&lt;/strong&gt;: install runtime components on EC2 and run deploy tasks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trivy&lt;/strong&gt;: container image vulnerability scanner integrated in pipeline&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ansible Vault&lt;/strong&gt;: secrets management for playbooks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prometheus + Grafana&lt;/strong&gt;: monitoring &amp;amp; dashboards (Prometheus scrapes Node Exporter + app metrics, Grafana visualizes)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jenkins Prometheus plugin&lt;/strong&gt;: optional for Jenkins metrics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optional&lt;/strong&gt;: SonarQube for code quality (can be Dockerized or external)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2 — Recommended folder structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;devsecops-pipeline-with-ansible-terraform/
├── app/
│   ├── Dockerfile
│   ├── app.py
│   └── requirements.txt
├── ansible/
│   ├── inventory.ini
│   ├── playbook.yml
│   ├── group_vars/
│   └── roles/
│       ├── flask_app/
│       │   ├── tasks/main.yml
│       │   └── templates/
│       ├── jenkins_setup/
│       └── monitoring/
├── terraform/
│   ├── main.tf
│   ├── variables.tf
│   ├── provider.tf
│   └── outputs.tf
├── Jenkinsfile
├── README.md
└── docs/
    └── workflow-mermaid.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3 — Prerequisites
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Local dev machine (Jenkins host or where you run CI):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Git, Docker, Python3, pip, Ansible, aws-cli v2, Trivy, ngrok (optional)&lt;/li&gt;
&lt;li&gt;Jenkins (installed either on a VM/container or as a system package)&lt;/li&gt;
&lt;li&gt;Jenkins user added to Docker group: &lt;code&gt;sudo usermod -aG docker jenkins&lt;/code&gt; (then restart/relauch session)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;AWS:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS account with ECR &amp;amp; EC2 ability&lt;/li&gt;
&lt;li&gt;An IAM user (for CI) with minimal policies for ECR push (AmazonEC2ContainerRegistryPowerUser or fine-grained)&lt;/li&gt;
&lt;li&gt;Key pair (private &lt;code&gt;.pem&lt;/code&gt;) you downloaded and will map to Terraform &lt;code&gt;key_name&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Security:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don’t commit private keys or AWS secrets. Use Jenkins credentials &amp;amp; Ansible Vault.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4 — Terraform: Provision EC2, SG, IAM (step-by-step)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Goals:&lt;/strong&gt; create three EC2 (flask, jenkins, monitoring) t3.micro (free-tier where available), create security group, IAM role/profile for ECR read/pull.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Basic pieces&lt;/strong&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Provider.tf
&lt;/h3&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%2Fl0oidr803pt6udukc6qq.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%2Fl0oidr803pt6udukc6qq.png" alt=" " width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  outputs.tf
&lt;/h3&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%2Fptzypdlxdcukiczqr7jv.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%2Fptzypdlxdcukiczqr7jv.png" alt=" " width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  main.tf
&lt;/h3&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%2Feann4y6hg7o7y4whaffd.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%2Feann4y6hg7o7y4whaffd.png" alt=" " width="800" height="443"&gt;&lt;/a&gt;&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%2Fj9qh1a61foiqfbwd5o45.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%2Fj9qh1a61foiqfbwd5o45.png" alt=" " width="800" height="440"&gt;&lt;/a&gt;&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%2Fp3pkoibv0d326ty0pwed.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%2Fp3pkoibv0d326ty0pwed.png" alt=" " width="800" height="439"&gt;&lt;/a&gt;&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%2Fs434u34oaa81myw31rtc.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%2Fs434u34oaa81myw31rtc.png" alt=" " width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Notes &amp;amp; tips:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Always use &lt;code&gt;key_name&lt;/code&gt; that matches an existing EC2 key pair (you create the key in AWS console once and reference its name).&lt;/li&gt;
&lt;li&gt;Lock SSH (&lt;code&gt;22&lt;/code&gt;) to your IP via CIDR for production safety.&lt;/li&gt;
&lt;li&gt;Avoid user_data for complex provisioning if you use Ansible to configure servers — keep Terraform for infra only.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  5 — Ansible: configure servers &amp;amp; deploy containers
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Inventory (&lt;code&gt;ansible/inventory.ini&lt;/code&gt;) example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[flask_server]
34.238.165.116 ansible_user=ubuntu

[jenkins_server]
18.207.168.154 ansible_user=ubuntu

[monitoring_server]
10.0.1.163 ansible_user=ubuntu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fmo7pbb7tbnkki630w04x.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%2Fmo7pbb7tbnkki630w04x.png" alt=" " width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Playbook (&lt;code&gt;ansible/playbook.yml&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flask_server&lt;/span&gt;
  &lt;span class="na"&gt;become&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
  &lt;span class="na"&gt;roles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;flask_app&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jenkins_server&lt;/span&gt;
  &lt;span class="na"&gt;become&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
  &lt;span class="na"&gt;roles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;jenkins_setup&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;monitoring_server&lt;/span&gt;
  &lt;span class="na"&gt;become&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
  &lt;span class="na"&gt;roles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;monitoring&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fe4yb2bj7abzb2ozustyf.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%2Fe4yb2bj7abzb2ozustyf.png" alt=" " width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Role &lt;code&gt;flask_app/tasks/main.yml&lt;/code&gt; (example):&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;flask_app_role&lt;/strong&gt;&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%2Fmn8avu5sm9yqx269mmnc.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%2Fmn8avu5sm9yqx269mmnc.png" alt=" " width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;jenkins_setup role&lt;/strong&gt;&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%2Falabwkkgbzffunbigyio.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%2Falabwkkgbzffunbigyio.png" alt=" " width="800" height="463"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- name: Install Docker &amp;amp; AWS CLI v2
  apt:
    name: ['docker.io', 'unzip', 'python3-pip']
    update_cache: yes
    state: present

- name: Ensure docker started
  systemd:
    name: docker
    state: started
    enabled: yes

- name: Install AWS CLI v2 (if not present) - script tasks...
- name: Log in to ECR
  shell: |
    aws ecr get-login-password --region {{ aws_region }} | docker login --username AWS --password-stdin {{ ecr_repo_domain }}
  environment: { AWS_ACCESS_KEY_ID: "{{ lookup('env','AWS_ACCESS_KEY_ID') }}" }
  args: { warn: false }
  register: login_result
  failed_when: login_result.rc != 0 and ('Unable to locate credentials' in login_result.stderr == False)

- name: Pull image
  docker_image:
    name: "{{ ecr_repo }}:{{ image_tag }}"
    source: pull
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Tips:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;docker_image&lt;/code&gt; module where possible.&lt;/li&gt;
&lt;li&gt;For ECR login, run with IAM role (preferred) or provide credentials via env/credentials file on host. If the EC2 has the appropriate IAM instance profile (ECR pull policy), you do not need to store AWS keys on the host.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;become: yes&lt;/code&gt; for system-level tasks.&lt;/li&gt;
&lt;li&gt;Avoid referencing local PEM path in &lt;code&gt;inventory.ini&lt;/code&gt; — use Jenkins &lt;code&gt;sshagent&lt;/code&gt; to provide keys at runtime. Inventory entries should be &lt;code&gt;ansible_user=ubuntu&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  6 — Jenkinsfile (CI pipeline — build, scan, push, deploy)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Key points:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Use Jenkins credentials:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;aws-credentials&lt;/code&gt; (AWS access key + secret) or use IAM role for Jenkins agent.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ansible-ec2-key&lt;/code&gt; (SSH private key)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Ensure &lt;code&gt;trivy&lt;/code&gt; is installed or install in pipeline before using it.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example Jenkinsfile&lt;/strong&gt;:&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%2Fumt502ntzre6z03329z0.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%2Fumt502ntzre6z03329z0.png" alt=" " width="800" height="441"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;
  &lt;span class="n"&gt;environment&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;AWS_REGION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'us-east-1'&lt;/span&gt;
    &lt;span class="n"&gt;ECR_REPO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'772954893641.dkr.ecr.us-east-1.amazonaws.com/flask-app'&lt;/span&gt;
    &lt;span class="n"&gt;IMAGE_TAG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"build-${BUILD_NUMBER}"&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;stages&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Checkout'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="nl"&gt;url:&lt;/span&gt; &lt;span class="s1"&gt;'https://github.com/ritesh355/devsecops-pipeline-with-ansible-terraform.git'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;branch:&lt;/span&gt;&lt;span class="s1"&gt;'main'&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Install Trivy if needed'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'''
          if ! command -v trivy &amp;gt;/dev/null 2&amp;gt;&amp;amp;1; then
            curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sudo sh -s -- -b /usr/local/bin
          fi
          trivy --version
        '''&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Build'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;script&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s2"&gt;"docker build -t ${ECR_REPO}:${IMAGE_TAG} ."&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Scan'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s2"&gt;"trivy image --exit-code 1 --severity HIGH,CRITICAL ${ECR_REPO}:${IMAGE_TAG} || true"&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Push to ECR'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;withCredentials&lt;/span&gt;&lt;span class="o"&gt;([[&lt;/span&gt;&lt;span class="n"&gt;$class&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'AmazonWebServicesCredentialsBinding'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;credentialsId:&lt;/span&gt; &lt;span class="s1"&gt;'aws-credentials'&lt;/span&gt;&lt;span class="o"&gt;]])&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'''
            aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${ECR_REPO}
            docker push ${ECR_REPO}:${IMAGE_TAG}
          '''&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Deploy via Ansible'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sshagent&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;credentials:&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'ansible-ec2-key'&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'''
           cd ansible
           ansible-playbook -i inventory.ini playbook.yml --limit flask_server -e "image_tag=${IMAGE_TAG}" 
          '''&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;always&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;cleanWs&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  output of CICD pipeline
&lt;/h3&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%2F63bstdq5tlvzuhdogmct.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%2F63bstdq5tlvzuhdogmct.png" alt=" " width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Notes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pass variables &lt;code&gt;image_tag&lt;/code&gt; and &lt;code&gt;ecr_repo&lt;/code&gt; to Ansible using &lt;code&gt;-e&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;sshagent&lt;/code&gt; Jenkins plugin and SSH credential type for the private key; ensure the credential ID matches.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  7 — Security: Trivy, SonarQube, Ansible Vault, IAM best practices
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Trivy&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integrate Trivy scan in pipeline. Fail builds for &lt;code&gt;HIGH/CRITICAL&lt;/code&gt; if policy requires.&lt;/li&gt;
&lt;li&gt;Keep a policy: fail when critical vuln found, allow medium/low with warnings.&lt;/li&gt;
&lt;/ul&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%2Fb4zycqdazyu585wojn2x.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%2Fb4zycqdazyu585wojn2x.png" alt=" " width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;SonarQube&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Optional code-quality &amp;amp; SAST. Could be run in Jenkins stage. Use Sonarqube scanner plugin.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Ansible Vault&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Store sensitive variables (e.g., DB passwords) in &lt;code&gt;group_vars/.../vault.yml&lt;/code&gt; encrypted with ansible-vault.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ansible-playbook -i inventory.ini playbook.yml --ask-vault-pass

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use &lt;code&gt;ansible-vault encrypt_string&lt;/code&gt; or &lt;code&gt;ansible-vault create&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In Jenkins, store the vault password in credentials and pass with &lt;code&gt;--vault-password-file&lt;/code&gt; or &lt;code&gt;--vault-id&lt;/code&gt; securely.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;these are the commands which i used&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run playbook with the encrypted inventory file
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ansible-playbook -i inventory.ini playbook.yml --ask-vault-pass
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Edit the encrypted inventory later
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ansible-vault edit inventory.ini
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Decrypt if needed
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   ansible-vault decrypt inventory.ini
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Jenkins credentials&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use Jenkins Credentials store (AWS keys, SSH keys, GitHub token). Never commit secrets.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;sshagent&lt;/code&gt; plugin to make SSH keys available to the build agent for the duration of the block.&lt;/li&gt;
&lt;/ul&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%2Fbj0gkh6q0q98cfuf9pbx.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%2Fbj0gkh6q0q98cfuf9pbx.png" alt=" " width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;IAM roles &amp;amp; policies&lt;/strong&gt;&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%2F2z1ag92zm07mnrnmzkj0.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%2F2z1ag92zm07mnrnmzkj0.png" alt=" " width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Use least-privilege:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ECR push/pull: &lt;code&gt;AmazonEC2ContainerRegistryPowerUser&lt;/code&gt; or custom policy limited to the repo.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&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%2Ftsch3nk3f0eo80cm2v2c.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%2Ftsch3nk3f0eo80cm2v2c.png" alt=" " width="800" height="442"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EC2 instance profile for servers that will &lt;code&gt;docker pull&lt;/code&gt; to fetch images should have ECR read access or use &lt;code&gt;AmazonEC2ContainerRegistryReadOnly&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Prefer instance profiles over hardcoded AWS keys on hosts.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  8 — Monitoring: Prometheus + Grafana + Node Exporter + Jenkins plugin
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Prometheus&lt;/strong&gt;&lt;br&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%2Fc29h6j7l3sy04bknbgrl.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%2Fc29h6j7l3sy04bknbgrl.png" alt=" " width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Add scrape targets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node Exporter on EC2 instances: &lt;code&gt;&amp;lt;ec2_private_ip&amp;gt;:9100&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Flask app (if instrumented): &lt;code&gt;&amp;lt;flask_ip&amp;gt;:5000/metrics&lt;/code&gt; (use &lt;code&gt;prometheus_flask_exporter&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Jenkins: &lt;code&gt;metrics_path: '/prometheus'&lt;/code&gt; (requires Prometheus plugin)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Grafana&lt;/strong&gt;&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%2F0bodxt345rgg8bnkfup1.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%2F0bodxt345rgg8bnkfup1.png" alt=" " width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add Prometheus datasource: URL &lt;code&gt;http://&amp;lt;prometheus_host&amp;gt;:9090&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Import dashboards:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Node Exporter Full (ID 1860)&lt;/strong&gt;&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%2Fja8gvvcey6l5d78h47bs.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%2Fja8gvvcey6l5d78h47bs.png" alt=" " width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Docker Monitoring → Dashboard ID: 12227&lt;/strong&gt;&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%2Fvri7z50pg8m1gcyy5dxe.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%2Fvri7z50pg8m1gcyy5dxe.png" alt=" " width="800" height="455"&gt;&lt;/a&gt;    &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prometheus 2.0 Stats → Dashboard ID: 3662&lt;/strong&gt;&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%2Fjdln0kwtzwqy47vvy8wj.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%2Fjdln0kwtzwqy47vvy8wj.png" alt=" " width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Set up Alerting in Grafana&lt;/strong&gt;&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%2Fss095ms5xtixhmrtdigg.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%2Fss095ms5xtixhmrtdigg.png" alt=" " width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  9 — Correct workflow (step-by-step) + diagram
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;High-level workflow&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Developer pushes code to GitHub.&lt;/li&gt;
&lt;li&gt;Jenkins job triggers on git push.&lt;/li&gt;
&lt;li&gt;Jenkins pulls code, builds Docker image.&lt;/li&gt;
&lt;li&gt;Jenkins runs Trivy scan.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;If Trivy finds critical issues → fail the build.

&lt;ol&gt;
&lt;li&gt;If scan passes → Jenkins logs in to ECR and pushes the image with tag (&lt;code&gt;build-N&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Jenkins calls Ansible (via &lt;code&gt;sshagent&lt;/code&gt;) passing &lt;code&gt;image_tag&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Ansible logs into target EC2 (using Ansible role with proper IAM or ECR login) and pulls the pushed image, stops old container and spins up a new one (docker run).&lt;/li&gt;
&lt;li&gt;Prometheus scrapes Node Exporter and application metrics; Grafana visualizes and triggers alerts.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  10 — Troubleshooting &amp;amp; common pitfalls
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ansible SSH fails&lt;/strong&gt;: make sure Jenkins loads private key via &lt;code&gt;sshagent&lt;/code&gt; and inventory does NOT hardcode &lt;code&gt;ansible_ssh_private_key_file&lt;/code&gt; pointing to a path that doesn’t exist on Jenkins agent. Use &lt;code&gt;ansible_user=ubuntu&lt;/code&gt; in inventory and &lt;code&gt;sshagent&lt;/code&gt; to supply key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ECR login failing&lt;/strong&gt;: ensure Jenkins has AWS credentials or EC2 instance running Ansible has IAM instance profile for ECR. Also use &lt;code&gt;aws ecr get-login-password | docker login&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker permission denied&lt;/strong&gt;: ensure Jenkins user in &lt;code&gt;docker&lt;/code&gt; group or run docker commands via sudo; prefer adding user to group and restarting session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prometheus YAML errors&lt;/strong&gt;: YAML is whitespace-sensitive. Use 2-space indentation and validate with &lt;code&gt;docker run --rm -v /path/prom.yml:/etc/prometheus/prometheus.yml prom/prometheus --config.file=/etc/prometheus/prometheus.yml&lt;/code&gt; to see parse errors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prometheus target 404&lt;/strong&gt;: target reachable but wrong path. For Jenkins use &lt;code&gt;/prometheus&lt;/code&gt; (plugin). For Node Exporter use &lt;code&gt;/metrics&lt;/code&gt; on port 9100.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trivy not found&lt;/strong&gt; in Jenkins: install Trivy system-wide or add an &lt;code&gt;Install Trivy&lt;/code&gt; stage in Jenkinsfile.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ansible variable recursion&lt;/strong&gt;: always pass required variables (&lt;code&gt;image_tag&lt;/code&gt;, &lt;code&gt;ecr_repo&lt;/code&gt;) from pipeline into Ansible (&lt;code&gt;-e "image_tag=${IMAGE_TAG} ecr_repo=${ECR_REPO}"&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  11 — Useful commands &amp;amp; snippets
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Docker run Prometheus (host-mounted config):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; prometheus &lt;span class="nt"&gt;-p&lt;/span&gt; 9090:9090 &lt;span class="nt"&gt;-v&lt;/span&gt; /home/ubuntu/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Start Node Exporter:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; node_exporter &lt;span class="nt"&gt;-p&lt;/span&gt; 9100:9100 prom/node-exporter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ECR login &amp;amp; push (shell):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ecr get-login-password &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1 | docker login &lt;span class="nt"&gt;--username&lt;/span&gt; AWS &lt;span class="nt"&gt;--password-stdin&lt;/span&gt; 772954893641.dkr.ecr.us-east-1.amazonaws.com
docker tag local-image:latest 772954893641.dkr.ecr.us-east-1.amazonaws.com/flask-app:build-1
docker push 772954893641.dkr.ecr.us-east-1.amazonaws.com/flask-app:build-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Ansible run (manual):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ansible-playbook &lt;span class="nt"&gt;-i&lt;/span&gt; ansible/inventory.ini ansible/playbook.yml &lt;span class="nt"&gt;--limit&lt;/span&gt; flask_server &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"image_tag=build-1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Validate Prometheus yaml (debug):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; /home/ubuntu/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus &lt;span class="nt"&gt;--config&lt;/span&gt;.file&lt;span class="o"&gt;=&lt;/span&gt;/etc/prometheus/prometheus.yml &lt;span class="nt"&gt;--log&lt;/span&gt;.level&lt;span class="o"&gt;=&lt;/span&gt;debug
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Final notes &amp;amp; tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Don’t store secrets in repo&lt;/strong&gt;. Use Jenkins credentials and Ansible Vault.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use IAM roles&lt;/strong&gt; for EC2 instances that need to pull images from ECR — avoids storing keys on servers.&lt;/li&gt;
&lt;li&gt;Test &lt;strong&gt;individual steps locally&lt;/strong&gt; first (Docker build &amp;amp; run, Ansible tasks to install Docker &amp;amp; pull image).&lt;/li&gt;
&lt;li&gt;Keep your &lt;strong&gt;prometheus.yml&lt;/strong&gt; simple and validate YAML syntax when editing.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  👨‍💻 Author
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Ritesh Singh&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://www.linkedin.com/in/ritesh-singh-092b84340/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://ritesh-devops.hashnode.dev/" rel="noopener noreferrer"&gt;Hashnode&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;💻&lt;a href="https://github.com/ritesh355/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://dev.to/ritesh355"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ansible</category>
      <category>terraform</category>
      <category>devsecops</category>
      <category>aws</category>
    </item>
    <item>
      <title>DevOps project: 🚀 Jenkins CI/CD Pipeline with Docker &amp; Node.js</title>
      <dc:creator>Ritesh Singh</dc:creator>
      <pubDate>Mon, 06 Oct 2025 14:01:07 +0000</pubDate>
      <link>https://dev.to/ritesh355/devops-project-jenkins-cicd-pipeline-with-docker-nodejs-2n16</link>
      <guid>https://dev.to/ritesh355/devops-project-jenkins-cicd-pipeline-with-docker-nodejs-2n16</guid>
      <description>&lt;h2&gt;
  
  
  🚀 Jenkins CI/CD Pipeline with Docker &amp;amp; Node.js
&lt;/h2&gt;

&lt;p&gt;This project demonstrates a &lt;strong&gt;Jenkins CI/CD pipeline&lt;/strong&gt; running on &lt;strong&gt;AWS EC2&lt;/strong&gt;, which builds and deploys a simple &lt;strong&gt;Node.js app&lt;/strong&gt; inside a &lt;strong&gt;Docker container&lt;/strong&gt;, and pushes the image to &lt;strong&gt;Docker Hub&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  📌 Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Node.js sample app (&lt;code&gt;Hello from Jenkins CI/CD + Docker + Node.js!&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Jenkins pipeline using &lt;strong&gt;Jenkinsfile&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Automated build &amp;amp; deployment with Docker&lt;/li&gt;
&lt;li&gt;Push Docker images to Docker Hub&lt;/li&gt;
&lt;li&gt;GitHub Webhook integration for auto builds&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛠️ Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Node.js&lt;/strong&gt; – Application&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker&lt;/strong&gt; – Containerization&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jenkins&lt;/strong&gt; – CI/CD pipeline&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS EC2&lt;/strong&gt; – Jenkins &amp;amp; Docker host&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker Hub&lt;/strong&gt; – Image registry&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt; – Source code repository&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  First Setting Up Jenkins on an AWS EC2 Instance
&lt;/h2&gt;

&lt;p&gt;This guide provides step-by-step instructions to launch an AWS EC2 instance, install Jenkins, and access the Jenkins server. Follow these steps to set up a Jenkins server using Amazon Linux 2 on a &lt;code&gt;t2.micro&lt;/code&gt; instance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;An AWS account with appropriate permissions.&lt;/li&gt;
&lt;li&gt;Basic knowledge of SSH and terminal commands.&lt;/li&gt;
&lt;li&gt;A web browser to access the Jenkins dashboard.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 1: Log in to an AWS Account
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to the &lt;a href="https://aws.amazon.com/console/" rel="noopener noreferrer"&gt;AWS Management Console&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Log in with your AWS credentials (username, password, and MFA if enabled).&lt;/li&gt;
&lt;li&gt;In the AWS Console, locate the &lt;strong&gt;EC2&lt;/strong&gt; service under the "Compute" section or use the search bar to find "EC2."&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;EC2&lt;/strong&gt; to access the EC2 Dashboard.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step 2: Navigate to EC2 Dashboard
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;In the EC2 Dashboard, select &lt;strong&gt;Instances&lt;/strong&gt; from the left-hand menu.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Launch instances&lt;/strong&gt; to start creating a new EC2 instance.
3.
&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%2Fgs62rvn8g73sag7mpmfy.png" alt=" " width="800" height="443"&gt; &lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step 3: Launch Instance
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;In the "Launch an instance" wizard, configure the following:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name&lt;/strong&gt;: Enter &lt;code&gt;my_jenkins_server&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Number of instances&lt;/strong&gt;: Set to &lt;code&gt;1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon Machine Image (AMI)&lt;/strong&gt;: Choose &lt;strong&gt;Amazon Linux 2 AMI (HVM), SSD Volume Type&lt;/strong&gt; (select the latest version available in your region).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architecture&lt;/strong&gt;: Select &lt;strong&gt;64-bit (x86)&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Proceed to configure instance details.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step 4: Configure Instance
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Instance Type&lt;/strong&gt;: Select &lt;strong&gt;t2.micro&lt;/strong&gt; (Free Tier eligible, 1 vCPU, 1 GiB memory).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key Pair&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;If you have an existing key pair, select it from the dropdown.&lt;/li&gt;
&lt;li&gt;If not, click &lt;strong&gt;Create new key pair&lt;/strong&gt;, name it (e.g., &lt;code&gt;jenkins-key&lt;/code&gt;), choose &lt;strong&gt;RSA&lt;/strong&gt; and &lt;strong&gt;.pem&lt;/strong&gt; format, and download the key pair. Store it securely.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Leave default settings for storage unless specific requirements exist.&lt;/li&gt;
&lt;li&gt;Proceed to configure network settings.
&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%2Fc8m1gv07qz9ohzrybhje.png" alt=" " width="800" height="438"&gt; &lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step 5: Configure Network Security Groups
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;In the &lt;strong&gt;Network settings&lt;/strong&gt; section:

&lt;ul&gt;
&lt;li&gt;Choose &lt;strong&gt;Create security group&lt;/strong&gt; or select an existing one.&lt;/li&gt;
&lt;li&gt;Add the following inbound rules:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Type&lt;/strong&gt;: HTTP, &lt;strong&gt;Protocol&lt;/strong&gt;: TCP, &lt;strong&gt;Port Range&lt;/strong&gt;: 8080, &lt;strong&gt;Source&lt;/strong&gt;: Anywhere (0.0.0.0/0) for Jenkins web access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type&lt;/strong&gt;: SSH, &lt;strong&gt;Protocol&lt;/strong&gt;: TCP, &lt;strong&gt;Port Range&lt;/strong&gt;: 22, &lt;strong&gt;Source&lt;/strong&gt;: Your IP or Anywhere (0.0.0.0/0) for SSH access.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security Note&lt;/strong&gt;: Allowing all traffic (0.0.0.0/0) for all ports is insecure. For production, restrict SSH to your IP and limit other traffic.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Ensure port 8080 (Jenkins) and port 22 (SSH) are open.&lt;/li&gt;
&lt;/ol&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%2F4nspab1r6mgbkgdia8kl.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%2F4nspab1r6mgbkgdia8kl.png" alt=" " width="800" height="419"&gt;&lt;/a&gt; &lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6: Review and Launch Instance
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Review the configuration (instance type, AMI, key pair, security group).&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Launch instance&lt;/strong&gt; to provision the instance.&lt;/li&gt;
&lt;li&gt;Note the instance ID from the confirmation message.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step 7: Connect to EC2 Instance
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;In the EC2 Dashboard, go to &lt;strong&gt;Instances&lt;/strong&gt; and wait for the instance to reach the &lt;strong&gt;Running&lt;/strong&gt; state (verify "Status Checks" pass).&lt;/li&gt;
&lt;li&gt;Select the instance (&lt;code&gt;my_jenkins_server&lt;/code&gt;) and click &lt;strong&gt;Connect&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&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%2Fado85fgrrl2aqp0isyrg.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%2Fado85fgrrl2aqp0isyrg.png" alt=" " width="800" height="442"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the &lt;strong&gt;Connect to instance&lt;/strong&gt; window, select the &lt;strong&gt;SSH client&lt;/strong&gt; tab.&lt;/li&gt;
&lt;/ol&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%2Fb17qtb59rjbnm6p18o02.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%2Fb17qtb59rjbnm6p18o02.png" alt=" " width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use the provided SSH command, e.g.:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   ssh &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"jenkins-key.pem"&lt;/span&gt; ec2-user@&amp;lt;Public_IP_or_DNS&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fc6so9lfzgovtxlcn9pti.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%2Fc6so9lfzgovtxlcn9pti.png" alt=" " width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Replace  with the instance’s public IP or DNS (found in instance details).&lt;/li&gt;
&lt;li&gt;Ensure the .pem file permissions are restricted:&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 8: Install Jenkins
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Connect to the instance via SSH, then run:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Update
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&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%2F3xojmetr08peag0luz5y.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%2F3xojmetr08peag0luz5y.png" alt=" " width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install Java (Jenkins needs Java)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install openjdk-17-jdk -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Frgjmfo70ychncqnr6dur.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%2Frgjmfo70ychncqnr6dur.png" alt=" " width="800" height="435"&gt;&lt;/a&gt;&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%2Fzlos0gqj54n6dfgb2h9j.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%2Fzlos0gqj54n6dfgb2h9j.png" alt=" " width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add Jenkins repository
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -fsSL https://pkg.jenkins.io/debian/jenkins.io-2023.key | sudo tee \
  /usr/share/keyrings/jenkins-keyring.asc &amp;gt; /dev/null
echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \
  https://pkg.jenkins.io/debian binary/ | sudo tee \
  /etc/apt/sources.list.d/jenkins.list &amp;gt; /dev/null

- Install Jenkins
sudo apt update -y
sudo apt install jenkins -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fm4ygb3h7xqelrzg6wol5.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%2Fm4ygb3h7xqelrzg6wol5.png" alt=" " width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt; Start Jenkins
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl start jenkins
sudo systemctl enable jenkins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 Jenkins runs on http://:8080&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 9: Configure Jenkins
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open browser → http://:8080&lt;/li&gt;
&lt;/ol&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%2Fpqu5juignp4l8nrw7n3f.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%2Fpqu5juignp4l8nrw7n3f.png" alt=" " width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get initial password:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo cat /var/lib/jenkins/secrets/initialAdminPassword
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fcofxxt7qpiytr722z15m.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%2Fcofxxt7qpiytr722z15m.png" alt=" " width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Paste password in Jenkins UI.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install suggested plugins.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2Fkrunx1jp30v1n93jdws1.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%2Fkrunx1jp30v1n93jdws1.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&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%2Fif6jng4z031y45osrr8k.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%2Fif6jng4z031y45osrr8k.png" alt=" " width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create admin user.&lt;/li&gt;
&lt;/ol&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%2F3lt3c32gh49ach9erajp.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%2F3lt3c32gh49ach9erajp.png" alt=" " width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;instance configuration&lt;/li&gt;
&lt;/ol&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%2Fi28ruf3g8o4e64zhrcpy.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%2Fi28ruf3g8o4e64zhrcpy.png" alt=" " width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;jenkins is ready now&lt;/li&gt;
&lt;/ol&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%2Fhpt00z5ac9mvbjfmmeig.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%2Fhpt00z5ac9mvbjfmmeig.png" alt=" " width="800" height="446"&gt;&lt;/a&gt;&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%2F3de5pfdrf26dubvsaq43.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%2F3de5pfdrf26dubvsaq43.png" alt=" " width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5: Install Docker on EC2
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install docker.io -y

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fqcfi2cbq3ma94ln2ce2g.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%2Fqcfi2cbq3ma94ln2ce2g.png" alt=" " width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;👉 Restart Jenkins so it can use Docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo usermod -aG docker jenkins
sudo systemctl enable docker
sudo systemctl start docker
sudo systemctl restart jenkins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Feob7f6564kub2gqj8y18.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%2Feob7f6564kub2gqj8y18.png" alt=" " width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;##  Create a GitHub Repository&lt;br&gt;
  ### Folder structure&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Docker-Jenkins-app/
│-- app.js
│-- package.json
│-- Dockerfile
│-- Jenkinsfile
│-- README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Configure Jenkins Pipeline
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Push your Docker-Jenkins-app repo to GitHub.&lt;/li&gt;
&lt;li&gt;In Jenkins UI:

&lt;ul&gt;
&lt;li&gt;New Item → Name: docker-pipeline-ec2 → Select Pipeline&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&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%2Foni14l3j32s5qzntet7d.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%2Foni14l3j32s5qzntet7d.png" alt=" " width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In Pipeline → Select Pipeline script from SCM&lt;/li&gt;
&lt;/ul&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%2F1wq63vjxkvenlzcmkuaa.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%2F1wq63vjxkvenlzcmkuaa.png" alt=" " width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;SCM: Git&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Repo URL: &lt;a href="https://github.com/ritesh355/Docker-Jenkins-app.git" rel="noopener noreferrer"&gt;https://github.com/ritesh355/Docker-Jenkins-app.git&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Branch: main&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2Fikpb3jvqipe9qgptk1uv.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%2Fikpb3jvqipe9qgptk1uv.png" alt=" " width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Setup GitHub Webhook
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to your repo → Settings → Webhooks → Add webhook. &lt;/li&gt;
&lt;/ol&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%2F8yg97rr75dd2ubjeqi0t.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%2F8yg97rr75dd2ubjeqi0t.png" alt=" " width="800" height="436"&gt;&lt;/a&gt;&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%2F0urn2xc99kbk00x84qpr.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%2F0urn2xc99kbk00x84qpr.png" alt=" " width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Payload URL:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://&amp;lt;EC2-Public-IP&amp;gt;:8080/github-webhook/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Content type: application/json&lt;/li&gt;
&lt;li&gt;Event: Just the push event&lt;/li&gt;
&lt;/ol&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%2F9537svh1t7nlaqvbxyme.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%2F9537svh1t7nlaqvbxyme.png" alt=" " width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;save&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Add Docker Hub Credentials in Jenkins
&lt;/h2&gt;

&lt;p&gt;Open Jenkins Dashboard → Manage Jenkins → Credentials.&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%2Fexcippfeijz8q750ny1f.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%2Fexcippfeijz8q750ny1f.png" alt=" " width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click System → Global credentials (unrestricted) → Add Credentials.&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%2Fep05zuxrmmimg8gh72m8.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%2Fep05zuxrmmimg8gh72m8.png" alt=" " width="800" height="441"&gt;&lt;/a&gt;&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%2Ftln8fqxc90ap7c43bswj.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%2Ftln8fqxc90ap7c43bswj.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select Kind = Username with password.&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%2Ftjxi2hn5zim8r1ysqv9p.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%2Ftjxi2hn5zim8r1ysqv9p.png" alt=" " width="800" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Username = Your Docker Hub username&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Password = Your Docker Hub password or personal access token
how to create docker hub tokens&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&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%2Fez01dfs2d8aejo4fqyuw.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%2Fez01dfs2d8aejo4fqyuw.png" alt=" " width="800" height="439"&gt;&lt;/a&gt;&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%2Fsrs5abg65yenz7crc0iz.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%2Fsrs5abg65yenz7crc0iz.png" alt=" " width="800" height="431"&gt;&lt;/a&gt;&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%2Fz2id27d6r689hrendgih.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%2Fz2id27d6r689hrendgih.png" alt=" " width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ID = dockerhub-creds (you will use this ID in Jenkinsfile)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Description = Docker Hub Credentials&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2F2q8xakz5ycyw3h2xytah.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%2F2q8xakz5ycyw3h2xytah.png" alt=" " width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Test
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Commit &amp;amp; push a small change to your repo (e.g., update app.js message).&lt;/li&gt;
&lt;li&gt;GitHub → Sends webhook → Jenkins job auto-triggers.&lt;/li&gt;
&lt;li&gt;Jenkins builds Docker image + runs container on EC2 And push the image into the docker hub
  &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%2Fs83u3rte450leo821eib.png" alt="image" width="800" height="444"&gt;
&lt;/li&gt;
&lt;/ol&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%2F8tx21zzvlzjmeln9fxyr.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%2F8tx21zzvlzjmeln9fxyr.png" alt=" " width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Access app at:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://&amp;lt;EC2-Public-IP&amp;gt;:4000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;✅ Now you’ll have a fully automated CI/CD pipeline on EC2 with webhooks.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  📢 Follow My Journey
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/ritesh355" rel="noopener noreferrer"&gt;github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/ritesh-singh-092b84340/" rel="noopener noreferrer"&gt;linkdin&lt;/a&gt;&lt;/p&gt;

</description>
      <category>jenkins</category>
      <category>cicd</category>
      <category>docker</category>
      <category>aws</category>
    </item>
    <item>
      <title>DevOps project:Mounting an EBS Volume on EC2</title>
      <dc:creator>Ritesh Singh</dc:creator>
      <pubDate>Fri, 03 Oct 2025 11:06:44 +0000</pubDate>
      <link>https://dev.to/ritesh355/mounting-an-ebs-volume-on-ec2-45n5</link>
      <guid>https://dev.to/ritesh355/mounting-an-ebs-volume-on-ec2-45n5</guid>
      <description>&lt;h1&gt;
  
  
  How to Attach and Mount Extra EBS Volume to Linux EC2 in AWS | Mounting EBS Volume
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🎯 Objective
&lt;/h2&gt;

&lt;p&gt;Learn how to &lt;strong&gt;attach, mount, and use an EBS volume&lt;/strong&gt; with an EC2 instance for persistent storage in AWS.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ AWS Services Used
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;EC2 (Elastic Compute Cloud)&lt;/strong&gt;: Instance to attach volume&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;EBS (Elastic Block Store)&lt;/strong&gt;: Persistent block storage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;IAM&lt;/strong&gt;: Proper permissions for EC2 access&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📋 Steps
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Create an EBS Volume
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Go to &lt;strong&gt;AWS Console → EC2 → Elastic Block Store → Volumes → Create Volume&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1759417635503%2F4bf40ca5-547c-4cea-a239-ad112c5a5369.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1759417635503%2F4bf40ca5-547c-4cea-a239-ad112c5a5369.png" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choose &lt;strong&gt;Volume type&lt;/strong&gt; (e.g., General Purpose SSD &lt;code&gt;gp3&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set &lt;strong&gt;Size&lt;/strong&gt; (e.g., 1 GB for testing)&lt;/p&gt;&lt;/li&gt;
&lt;li&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1759417739275%2Fe6aa388e-ec57-40c1-86b9-f2dcc6ace340.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1759417739275%2Fe6aa388e-ec57-40c1-86b9-f2dcc6ace340.png" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select the &lt;strong&gt;same Availability Zone&lt;/strong&gt; as your EC2 instance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;strong&gt;Create Volume&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  2. Attach Volume to EC2
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;firstly launce an ec2 instance in same availability zone&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Select the volume → &lt;strong&gt;Actions → Attach Volume&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&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%2Fikp7txiyxkkog4krkohf.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%2Fikp7txiyxkkog4krkohf.png" width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choose the &lt;strong&gt;EC2 instance&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;strong&gt;Attach&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1759418074291%2Fb9c80494-a812-4b68-981a-bb8043c004f3.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1759418074291%2Fb9c80494-a812-4b68-981a-bb8043c004f3.png" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Connect to EC2 &amp;amp; Mount Volume
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;SSH into your EC2 instance:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-i&lt;/span&gt; mykey.pem ec2-user@&amp;lt;EC2-Public-IP&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1759418318015%2F1e9628c6-10df-43b1-a9c2-f0f6e2a93d83.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1759418318015%2F1e9628c6-10df-43b1-a9c2-f0f6e2a93d83.png" alt="after ssh switch to root user using sudo su -" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2 . After ssh switch into root user&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo su -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3 . use command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;df -h 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4 . Format the Volume (if needed)&lt;/p&gt;

&lt;p&gt;Check if filesystem exists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo file -s /dev/nvme1n1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If output shows &lt;code&gt;data&lt;/code&gt;, format it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mkfs -t ext4 /dev/nvme1n1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note —&amp;gt; replace with your disk name like /dev/xvdf in my case it is not xvdf it is nvme1n1&lt;/strong&gt;&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1759419214413%2Ffe91692b-af15-414b-aecb-b9121b75a15f.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1759419214413%2Ffe91692b-af15-414b-aecb-b9121b75a15f.png" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Mount the Volume
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create a mount point:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mkdir /mnt/myvolume
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Mount it:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mount /dev/nvme1n1 /mnt/myvolume
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Verify:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    df -h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;![](https://cdn.hashnode.com/res/hashnode/image/upload/v1759419506610/7160c0f9-5438-429f-8f06-4e43d488d0ae.png )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;## 🌐 Connect With Me&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;💻 GitHub: &lt;a href="https://github.com/ritesh355" rel="noopener noreferrer"&gt;ritesh355&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;📝 Blog: &lt;a href="http://ritesh-devops.hashnode.dev" rel="noopener noreferrer"&gt;ritesh-devops.hashnode.dev&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;💼 LinkedIn: &lt;a href="https://linkedin.com/in/ritesh-singh-092b84340" rel="noopener noreferrer"&gt;Ritesh Singh&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>ec2</category>
      <category>ebs</category>
      <category>devops</category>
    </item>
    <item>
      <title>🚀 Building &amp; Deploying My Next.js Portfolio with Docker, AWS, CI/CD and monitoring with Promithius and Grafana"</title>
      <dc:creator>Ritesh Singh</dc:creator>
      <pubDate>Mon, 22 Sep 2025 16:03:17 +0000</pubDate>
      <link>https://dev.to/ritesh355/building-deploying-my-nextjs-portfolio-with-docker-aws-and-cicd-54cf</link>
      <guid>https://dev.to/ritesh355/building-deploying-my-nextjs-portfolio-with-docker-aws-and-cicd-54cf</guid>
      <description>&lt;h1&gt;
  
  
  🚀 Next.js Portfolio – DevOps Ready
&lt;/h1&gt;

&lt;p&gt;This is &lt;strong&gt;Personal Portfolio Project&lt;/strong&gt;  built with &lt;strong&gt;Next.js&lt;/strong&gt;, containerized using &lt;strong&gt;Docker&lt;/strong&gt;, deployed on &lt;strong&gt;AWS EC2 (Free Tier)&lt;/strong&gt;, and distributed globally via &lt;strong&gt;AWS CloudFront CDN&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The deployment pipeline is fully automated using &lt;strong&gt;GitHub Actions (CI/CD)&lt;/strong&gt; — from building the Docker image to pushing it to &lt;strong&gt;Docker Hub&lt;/strong&gt; and deploying it on &lt;strong&gt;EC2&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For performance and container health monitoring, the project integrates a &lt;strong&gt;Monitoring Stack&lt;/strong&gt; using &lt;strong&gt;Prometheus&lt;/strong&gt;, &lt;strong&gt;Grafana&lt;/strong&gt;, and &lt;strong&gt;cAdvisor&lt;/strong&gt;, all connected through a shared Docker network.&lt;/p&gt;

&lt;p&gt;It demonstrates both &lt;strong&gt;frontend skills (React/Next.js)&lt;/strong&gt; and &lt;strong&gt;DevOps practices (CI/CD, Docker, DockerHub ,aws ,cloudfront, promithius and grafana)&lt;/strong&gt;.  &lt;/p&gt;

&lt;h2&gt;
  
  
  ⚡ Workflow
&lt;/h2&gt;

&lt;h3&gt;
  
  
  DevOps Workflow
&lt;/h3&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%2Fu4695je8tevj7q4uifra.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%2Fu4695je8tevj7q4uifra.png" alt=" " width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📸 Screenshots
&lt;/h2&gt;

&lt;h3&gt;
  
  
  about
&lt;/h3&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%2Fxecot2x7jtkcp0ne5cdc.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%2Fxecot2x7jtkcp0ne5cdc.png" alt="Homepage" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  skills
&lt;/h3&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%2Fpgtg22rhvvpnfl183s09.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%2Fpgtg22rhvvpnfl183s09.png" alt="Homepage" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ✨ Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;⚛️ Modern portfolio built with &lt;strong&gt;Next.js&lt;/strong&gt; (SSR + React 18).&lt;/li&gt;
&lt;li&gt;📱 Responsive design for desktop &amp;amp; mobile.&lt;/li&gt;
&lt;li&gt;🐳 Fully &lt;strong&gt;Dockerized&lt;/strong&gt; (multi-stage build, production optimized).&lt;/li&gt;
&lt;li&gt;☁️ Deployed on &lt;strong&gt;AWS EC2 Free Tier&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;🔄 Automated &lt;strong&gt;CI/CD pipeline&lt;/strong&gt; with GitHub Actions:

&lt;ul&gt;
&lt;li&gt;Runs tests (&lt;code&gt;npm run build&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Builds and pushes Docker image to DockerHub.&lt;/li&gt;
&lt;li&gt;SSH into EC2 and redeploys automatically.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;📜 .&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛠️ Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: Next.js, React, Tailwind CSS
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Containerization&lt;/strong&gt;: Docker, DockerHub
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD&lt;/strong&gt;: GitHub Actions
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud&lt;/strong&gt;: AWS EC2 (Ubuntu 22.04, Free Tier)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IaC&lt;/strong&gt;: Terraform
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📂 Project Structure
&lt;/h2&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%2F6ekpnf7i7rtdyqowdpef.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%2F6ekpnf7i7rtdyqowdpef.png" alt="Homepage" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  💻 Run Locally
&lt;/h2&gt;

&lt;p&gt;Clone the repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone git@github.com:ritesh355/portfolio.git
cd portfolio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run dev server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then visit &lt;strong&gt;&lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📦 Docker Setup
&lt;/h2&gt;

&lt;p&gt;Build the image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t ritesh355/nextjs-portfolio:latest .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;run the container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -d -p 3000:3000 ritesh355/nextjs-portfolio:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then visit &lt;strong&gt;&lt;em&gt;&lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ☁️ Deployment on AWS EC2
&lt;/h2&gt;

&lt;p&gt;1.Launch Ubuntu EC2 Free Tier.&lt;br&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%2F8qo5hwvuacp9vf5jmwhe.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%2F8qo5hwvuacp9vf5jmwhe.png" alt="Homepage" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2.after connetint that ec2 Install Docker:&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 docker.io
sudo usermod -aG docker ubuntu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Pull and run image:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  docker pull ritesh355/nextjs-portfolio:latest
docker run -d -p 80:3000 ritesh355/nextjs-portfolio:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4.Visit &lt;a href="http://EC2-Public-IP" rel="noopener noreferrer"&gt;http://EC2-Public-IP&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🤖 GitHub Actions CI/CD
&lt;/h2&gt;

&lt;p&gt;Located in .github/workflows/main.yml:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Runs tests (npm run build).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Builds &amp;amp; pushes image to DockerHub.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SSH into EC2, pulls new image, restarts container.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example Workflow&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: Build, Push &amp;amp; Deploy with Rollback

on:
  push:
    branches:
      - main

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
    # 1. Checkout repo
    - name: Checkout code
      uses: actions/checkout@v3

    # 2. Setup Node.js
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'

    # 3. Install dependencies
    - name: Install dependencies
      run: npm install --legacy-peer-deps

    # 4. Run build
    - name: Build project
      run: npm run build

    # 5. Log in to Docker Hub
    - name: Log in to Docker Hub
      uses: docker/login-action@v2
      with:
        username: ${{ secrets.DOCKER_USERNAME }}
        password: ${{ secrets.DOCKER_PASSWORD }}

    # 6. Build Docker image
    - name: Build Docker image
      run: |
        docker build -t ritesh355/nextjs-portfolio:latest \
                     -t ritesh355/nextjs-portfolio:v1 \
                     -t ritesh355/nextjs-portfolio:v1.0.0 .

    # 7. Push Docker image
    - name: Push Docker image
      run: |
        docker push ritesh355/nextjs-portfolio:latest
        docker push ritesh355/nextjs-portfolio:v1
        docker push ritesh355/nextjs-portfolio:v1.0.0

    # 8. Deploy to EC2 with rollback
    - name: Deploy to EC2
      uses: appleboy/ssh-action@v0.1.9
      with:
        host: ${{ secrets.EC2_HOST }}
        username: ${{ secrets.EC2_USER }}
        key: ${{ secrets.EC2_SSH_KEY }}
        script: |
          echo "Pulling latest Docker image..."
          docker pull ritesh355/nextjs-portfolio:latest

          # Backup old container if exists
          if docker ps -a --format '{{.Names}}' | grep -Eq "^nextjs-portfolio\$"; then
            echo "Backing up current container..."
            docker rename nextjs-portfolio nextjs-portfolio-backup
          fi

          # Run new container
          echo "Starting new container..."
          docker run -d --name nextjs-portfolio -p 80:3000 ritesh355/nextjs-portfolio:latest

          # Check if container is running
          sleep 5
          if ! docker ps --format '{{.Names}}' | grep -Eq "^nextjs-portfolio\$"; then
            echo "New container failed! Rolling back..."
            docker rm nextjs-portfolio || true
            docker rename nextjs-portfolio-backup nextjs-portfolio || true
            docker start nextjs-portfolio || true
          else
            echo "Deployment successful! Removing backup..."
            docker rm -f nextjs-portfolio-backup || true
          fi

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  📊 Monitoring Stack
&lt;/h2&gt;

&lt;p&gt;To monitor the Next.js portfolio container, I implemented a full container monitoring setup using &lt;strong&gt;Prometheus, Grafana, and cAdvisor&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Steps Implemented
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run cAdvisor container&lt;/strong&gt; to collect metrics:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;cadvisor &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--network&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;monitoring &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; /:/rootfs:ro &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; /var/run:/var/run:ro &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; /sys:/sys:ro &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; /var/lib/docker/:/var/lib/docker:ro &lt;span class="se"&gt;\&lt;/span&gt;
  gcr.io/cadvisor/cadvisor:v0.47.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fj3s3h61jxq9ydsba6q5g.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%2Fj3s3h61jxq9ydsba6q5g.png" alt=" " width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Run Prometheus container with cAdvisor&lt;/strong&gt; target:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -d \
  --name=prometheus \
  --network=monitoring \
  -p 9090:9090 \
  -v /etc/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml \
  prom/prometheus
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fad7ypb7j9fjjk95gq8kv.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%2Fad7ypb7j9fjjk95gq8kv.png" alt=" " width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Prometheus configuration&lt;/strong&gt; (/etc/prometheus/prometheus.yml):
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;global:
  scrape_interval: 5s

scrape_configs:
  - job_name: 'cadvisor'
    static_configs:
      - targets: ['cadvisor:8080']

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fso31jfqvc5749omi1gxy.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%2Fso31jfqvc5749omi1gxy.png" alt=" " width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run &lt;strong&gt;Grafana container&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -d \
  --name=grafana \
  --network=monitoring \
  -p 3001:3000 \
  grafana/grafana

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fq1s6m86hmuviedw299br.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%2Fq1s6m86hmuviedw299br.png" alt=" " width="800" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  👨‍💻 Author
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Ritesh Singh&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://www.linkedin.com/in/ritesh-singh-092b84340/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; |&lt;br&gt;
📝 &lt;a href="https://ritesh-devops.hashnode.dev/" rel="noopener noreferrer"&gt;Hashnode&lt;/a&gt; |&lt;br&gt;
💻&lt;a href="https://github.com/ritesh355/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;⚡ Built with ❤️ using Next.js + Docker + AWS + DevOps&lt;/p&gt;

</description>
      <category>devops</category>
      <category>githubactions</category>
      <category>aws</category>
      <category>docker</category>
    </item>
  </channel>
</rss>
