<?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: Vivek Singh</title>
    <description>The latest articles on DEV Community by Vivek Singh (@developedbyviv).</description>
    <link>https://dev.to/developedbyviv</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%2F1229184%2F84541dc9-0dfa-45ac-a2d2-fc02705e95ee.png</url>
      <title>DEV Community: Vivek Singh</title>
      <link>https://dev.to/developedbyviv</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/developedbyviv"/>
    <language>en</language>
    <item>
      <title>🚀 Building a Real-World CI/CD Pipeline with Jenkins, Docker, and Docker Compose</title>
      <dc:creator>Vivek Singh</dc:creator>
      <pubDate>Sat, 24 Jan 2026 21:46:50 +0000</pubDate>
      <link>https://dev.to/developedbyviv/building-a-real-world-cicd-pipeline-with-jenkins-docker-and-docker-compose-4afp</link>
      <guid>https://dev.to/developedbyviv/building-a-real-world-cicd-pipeline-with-jenkins-docker-and-docker-compose-4afp</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;From broken builds to a fully automated deployment pipeline.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As part of my DevOps learning journey, I wanted to build something practical, realistic, and close to production workflows — not just follow tutorials.&lt;/p&gt;

&lt;p&gt;So I built a two-tier web application and automated its entire build, test, and deployment lifecycle using Jenkins, Docker, and Docker Compose.&lt;/p&gt;

&lt;p&gt;This article walks through:&lt;br&gt;
    • The architecture I built&lt;br&gt;
    • The CI/CD pipeline design&lt;br&gt;
    • Real issues I faced (and fixed)&lt;br&gt;
    • Key DevOps learnings&lt;/p&gt;


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

&lt;p&gt;The goal was simple but important:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Automate everything from code commit to deployment — with no manual steps.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tech Stack&lt;br&gt;
    • Frontend / API: Flask (Python)&lt;br&gt;
    • Database: MySQL&lt;br&gt;
    • CI/CD: Jenkins (Pipeline as Code)&lt;br&gt;
    • Containerization: Docker&lt;br&gt;
    • Orchestration: Docker Compose&lt;br&gt;
    • Version Control: GitHub&lt;/p&gt;


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

&lt;p&gt;The application follows a classic two-tier architecture:&lt;br&gt;
    • Web tier: Flask application&lt;br&gt;
    • Data tier: MySQL database&lt;br&gt;
    • Both services run in separate Docker containers&lt;br&gt;
    • Managed via Docker Compose&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GitHub
  ↓
Jenkins Pipeline
  ↓
Docker Build
  ↓
Tests
  ↓
Docker Compose Deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🐳 Docker &amp;amp; Docker Compose Setup
&lt;/h2&gt;

&lt;p&gt;Docker Compose is used to define and run multiple containers together.&lt;/p&gt;

&lt;p&gt;Services:&lt;br&gt;
    • db: MySQL 8 container&lt;br&gt;
    • web: Flask application container&lt;/p&gt;

&lt;p&gt;Key highlights:&lt;br&gt;
    • Database initialization using init.sql&lt;br&gt;
    • Environment variables for DB connectivity&lt;br&gt;
    • Service dependency (web depends on db)&lt;/p&gt;

&lt;p&gt;📸 Image: docker-compose.yml (services definition)&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%2F9y4joyoo6hcy3uynr1a1.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%2F9y4joyoo6hcy3uynr1a1.png" alt=" " width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🐍 Flask Application
&lt;/h2&gt;

&lt;p&gt;The Flask app exposes simple endpoints:&lt;br&gt;
    • / → health check&lt;br&gt;
    • /users → fetches data from MySQL&lt;/p&gt;

&lt;p&gt;The database connection is handled using environment variables, making the app environment-agnostic.&lt;/p&gt;

&lt;p&gt;📸 Image: db.py (MySQL connection using env variables)&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%2F3rw44sm3f5eb7v8rha16.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%2F3rw44sm3f5eb7v8rha16.png" alt=" " width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📸 Image: app.py (Flask routes and app runner)&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%2Fbttqwwxjtnuyy1jget58.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%2Fbttqwwxjtnuyy1jget58.png" alt=" " width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This design ensures:&lt;br&gt;
    • No hardcoded credentials&lt;br&gt;
    • Easy containerization&lt;br&gt;
    • Smooth CI/CD execution&lt;/p&gt;




&lt;h2&gt;
  
  
  🐋 Dockerfile (Application Image)
&lt;/h2&gt;

&lt;p&gt;The Flask app is containerized using a simple, optimized Dockerfile:&lt;br&gt;
    • Lightweight base image (python:3.9-slim)&lt;br&gt;
    • Dependency installation via requirements.txt&lt;br&gt;
    • Exposes port 5000&lt;br&gt;
    • Runs the app using CMD&lt;/p&gt;

&lt;p&gt;📸 Image: Dockerfile&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%2Fd21ha4tl9cs45roosrhb.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%2Fd21ha4tl9cs45roosrhb.png" alt=" " width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ Jenkins CI/CD Pipeline
&lt;/h2&gt;

&lt;p&gt;This is where the real DevOps work happens.&lt;/p&gt;

&lt;p&gt;The pipeline is written using Jenkins Declarative Pipeline and stored as a Jenkinsfile in the repository.&lt;/p&gt;

&lt;p&gt;Pipeline Stages:&lt;br&gt;
    1.  Checkout – Pull source code from GitHub&lt;br&gt;
    2.  Build Image – Build Docker images using Docker Compose&lt;br&gt;
    3.  Run Tests – Start DB container and validate application&lt;br&gt;
    4.  Deploy – Bring up all services using Docker Compose&lt;/p&gt;

&lt;p&gt;📸 Image: Jenkinsfile (pipeline stages)&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%2F5rxuoq3mb6ft94zkz0p7.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%2F5rxuoq3mb6ft94zkz0p7.png" alt=" " width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📊 Jenkins Stage View (Pipeline Execution)
&lt;/h2&gt;

&lt;p&gt;The Jenkins Stage View clearly shows:&lt;br&gt;
    • Which stage failed&lt;br&gt;
    • How long each stage took&lt;br&gt;
    • When the pipeline finally turned green&lt;/p&gt;

&lt;p&gt;This helped massively during debugging.&lt;/p&gt;

&lt;p&gt;📸 Image: Jenkins Stage View (failed → successful build)&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%2Fo09a9t9ggjgplgws0pj0.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%2Fo09a9t9ggjgplgws0pj0.png" alt=" " width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🧨 Real Issues I Faced (and Fixed)
&lt;/h2&gt;

&lt;p&gt;This project was not smooth, and that’s where the learning came from.&lt;/p&gt;

&lt;p&gt;🔴 Issue 1: Jenkins couldn’t find Jenkinsfile&lt;br&gt;
    • Root cause: Case sensitivity&lt;br&gt;
    • jenkinsfile ≠ Jenkinsfile&lt;/p&gt;

&lt;p&gt;✅ Fixed by forcing correct filename in Git&lt;/p&gt;




&lt;h2&gt;
  
  
  🔴 Issue 2: docker: not found in Jenkins
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;• Jenkins was running inside a container
• Docker CLI wasn’t available inside Jenkins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;✅ Installed Docker CLI inside Jenkins container&lt;/p&gt;




&lt;h2&gt;
  
  
  🔴 Issue 3: Docker Compose v1 vs v2 mismatch
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;• Jenkins environment only had docker-compose
• Pipeline was using docker compose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;✅ Aligned Jenkinsfile with available tooling&lt;/p&gt;




&lt;h2&gt;
  
  
  🔴 Issue 4: Permission denied on /var/run/docker.sock
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;• Jenkins user couldn’t talk to Docker daemon
• Linux socket permission issue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;✅ Fixed by adjusting Docker socket permissions (for local CI)&lt;/p&gt;




&lt;p&gt;✅ Final Result&lt;/p&gt;

&lt;p&gt;After resolving all issues:&lt;br&gt;
    • ✔ Fully automated CI/CD pipeline&lt;br&gt;
    • ✔ Build → Test → Deploy without manual steps&lt;br&gt;
    • ✔ Dockerized multi-container application&lt;br&gt;
    • ✔ Jenkins pipeline running clean and green&lt;/p&gt;

&lt;p&gt;📸 Image: Successful Jenkins pipeline run&lt;/p&gt;




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

&lt;p&gt;This project taught me far more than any tutorial:&lt;br&gt;
    • DevOps is more about debugging systems than writing YAML&lt;br&gt;
    • Linux fundamentals matter a lot&lt;br&gt;
    • CI/CD environments behave differently than local machines&lt;br&gt;
    • Logs are your best debugging tool&lt;br&gt;
    • Small permission issues can break entire pipelines&lt;br&gt;
    • Automation only works when every layer is understood&lt;/p&gt;




&lt;h2&gt;
  
  
  🔗 Source Code
&lt;/h2&gt;

&lt;p&gt;GitHub Repository:&lt;br&gt;
👉 &lt;a href="https://github.com/developedbyviv/Two-tier-Architecture-Application" rel="noopener noreferrer"&gt;https://github.com/developedbyviv/Two-tier-Architecture-Application&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>jenkins</category>
      <category>docker</category>
      <category>cicd</category>
    </item>
    <item>
      <title>I Passed the GitHub Foundations Certification: My Honest Experience</title>
      <dc:creator>Vivek Singh</dc:creator>
      <pubDate>Fri, 29 Nov 2024 17:56:26 +0000</pubDate>
      <link>https://dev.to/developedbyviv/i-passed-the-github-foundations-certification-my-honest-experience-1mmi</link>
      <guid>https://dev.to/developedbyviv/i-passed-the-github-foundations-certification-my-honest-experience-1mmi</guid>
      <description>&lt;p&gt;Recently, I had the opportunity to take the GitHub Foundations Certification exam, thanks to a free voucher from Wipro. After working with Git and GitHub for quite some time, I decided to put my knowledge to the test. Here's my honest take on the whole experience—from preparation to the actual exam.&lt;/p&gt;




&lt;p&gt;📝 Exam Details&lt;/p&gt;

&lt;p&gt;Format: 75 multiple-choice questions (60 scored + 15 pretest questions)&lt;/p&gt;

&lt;p&gt;Duration: 120 minutes&lt;/p&gt;

&lt;p&gt;Preparation Materials:&lt;/p&gt;

&lt;p&gt;GitHub Certification Guide&lt;/p&gt;

&lt;p&gt;FreeCodeCamp GitHub Course by Andrew Brown&lt;/p&gt;

&lt;p&gt;Free Voucher Code: I used the code USUUMWDS during checkout on the GitHub exam registration site. (Not sure if it’s still valid, but worth trying!)&lt;/p&gt;




&lt;p&gt;💡 What I Liked About the Exam&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Practicality: The questions focus on real-life scenarios, making it an excellent way to refresh your knowledge of Git and GitHub.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bite-Sized Insights: The exam covers a wide range of topics, ensuring you’re well-versed in GitHub workflows, Git commands, and collaboration practices.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Quick to Complete: I finished the exam in just 40 minutes, leaving me surprised at how manageable it was overall.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;😅 What I Struggled With&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Details Overload: Some questions required memorizing extensive details, like the 25 events that can trigger GitHub workflows. Realistically, this level of detail is hard to recall, even for frequent GitHub users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pretest Questions: It was unclear which questions were pretests and which were scored, which added an extra layer of uncertainty.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;My Preparation Strategy&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Certification Guide: I studied the GitHub Certification Guide, which provided a solid foundation of the key topics.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;FreeCodeCamp Course: Andrew Brown’s YouTube course was a lifesaver, especially for visualizing concepts like pull requests, branching strategies, and Git commands.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Practice in Real Projects: The best preparation was applying these skills in actual projects. Real-world experience made it easier to answer scenario-based questions.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Final Thoughts&lt;/p&gt;

&lt;p&gt;Passing this certification felt like a rewarding milestone. Even though I skipped a few questions and felt unsure about some answers, I managed to succeed! This certification isn't just about memorizing commands—it’s about understanding workflows, collaboration, and the power of GitHub in software development.&lt;/p&gt;

&lt;p&gt;If you’re planning to take this exam, I’d recommend focusing on practical knowledge and using the resources mentioned above. And if you don’t pass on the first try, don’t stress—every attempt will make you better!&lt;/p&gt;

&lt;p&gt;Have you taken the GitHub Foundations Certification exam? Share your experience in the comments below—I’d love to hear your thoughts!&lt;/p&gt;




&lt;p&gt;Tags: #GitHub #Certification #Git #Career #DevOps&lt;/p&gt;

</description>
      <category>github</category>
      <category>certification</category>
      <category>git</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
