<?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>Forem: Muhammad Ishaq</title>
    <description>The latest articles on Forem by Muhammad Ishaq (@muhammad_ishaq_955f95dfa2).</description>
    <link>https://forem.com/muhammad_ishaq_955f95dfa2</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%2F3328764%2F631df0fe-4a63-414f-8816-9152eaa388ee.png</url>
      <title>Forem: Muhammad Ishaq</title>
      <link>https://forem.com/muhammad_ishaq_955f95dfa2</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/muhammad_ishaq_955f95dfa2"/>
    <language>en</language>
    <item>
      <title>🚀 Deploying a Gallery App with Docker, Jenkins, and EC2..</title>
      <dc:creator>Muhammad Ishaq</dc:creator>
      <pubDate>Wed, 24 Sep 2025 00:34:09 +0000</pubDate>
      <link>https://forem.com/muhammad_ishaq_955f95dfa2/deploying-a-gallery-app-with-docker-jenkins-and-ec2-2p6b</link>
      <guid>https://forem.com/muhammad_ishaq_955f95dfa2/deploying-a-gallery-app-with-docker-jenkins-and-ec2-2p6b</guid>
      <description>&lt;h4&gt;
  
  
  In this article, we’ll walk through the journey of building, containerizing, scanning, and deploying a React + Firebase Gallery App using Docker, Jenkins CI/CD, and AWS EC2.
&lt;/h4&gt;

&lt;h4&gt;
  
  
  This guide is written so that even if you are new to DevOps or cloud deployment, you can follow step by step and understand why each part matters.
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/muhammadiishaq/Gallery-Website-Deploy-" rel="noopener noreferrer"&gt;Project Repo Link..&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  📸 About the Project
&lt;/h2&gt;

&lt;h3&gt;
  
  
  This is a simple Gallery App built with:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;React (frontend)&lt;/li&gt;
&lt;li&gt;Firebase (authentication + storage)&lt;/li&gt;
&lt;li&gt;TailwindCSS (styling)&lt;/li&gt;
&lt;li&gt;The app allows you to:&lt;/li&gt;
&lt;li&gt;Upload and download images&lt;/li&gt;
&lt;li&gt;Log in/out securely&lt;/li&gt;
&lt;li&gt;Manage your personal gallery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While the app itself is simple, the real power comes in how we deploy it. We’ll use modern DevOps practices to ensure the app can be shipped quickly, securely, and reliably.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚡ Step 1: Running Locally
&lt;/h2&gt;

&lt;p&gt;Before thinking about Docker or Jenkins, you should always confirm the app runs locally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Clone the repo:...&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;git clone https://github.com/your-username/gallery-app.git
cd gallery-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Install dependencies:&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;npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Start development server:&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;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;By default, the app is available at:&lt;/strong&gt;&lt;br&gt;
👉&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;http://localhost:5173&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. For a production build:..&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;npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a dist/ folder containing optimized static assets.&lt;/p&gt;

&lt;h2&gt;
  
  
  🐳 Step 2: Containerizing with Docker
&lt;/h2&gt;

&lt;p&gt;Instead of manually building and serving files, let’s use Docker. Docker helps us ship the app anywhere without worrying about environment differences.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Stage 1: Build the app
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# Stage 2: Serve with Nginx
FROM nginx:alpine
RUN rm -rf /usr/share/nginx/html/*
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;👉 Why multi-stage?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First stage (node:18-alpine) builds the React app.&lt;/li&gt;
&lt;li&gt;Second stage (nginx:alpine) serves only the optimized static files.&lt;/li&gt;
&lt;li&gt;This keeps the final image lightweight and production-ready.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;To build and run:&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;docker build -t gallery-app:latest .
docker run -d -p 80:80 --name gallery-app-cont gallery-app:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Now, open &lt;a href="http://localhost" rel="noopener noreferrer"&gt;http://localhost&lt;/a&gt; and your app is live 🎉&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚙️ Step 3: Automating with Jenkins
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Manual builds are fine for testing, but in real-world projects we use CI/CD pipelines to automate everything.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We’ll use Jenkins on EC2 to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clone the code&lt;/li&gt;
&lt;li&gt;Build Docker image&lt;/li&gt;
&lt;li&gt;Scan image with Trivy (security scan)&lt;/li&gt;
&lt;li&gt;Push to DockerHub&lt;/li&gt;
&lt;li&gt;Deploy container on EC2
**
👉 A Jenkinsfile is already included in the repository. Make sure to review it for the full pipeline definition.**&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔒 Step 4: Security Scanning with Trivy
&lt;/h2&gt;

&lt;p&gt;Security is critical. That’s why before pushing our image to DockerHub,First check that trivy install and update.. &lt;br&gt;
we run:..&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;trivy image gallery-app:latest

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

&lt;/div&gt;



&lt;p&gt;This checks for vulnerabilities in our base images (node:18-alpine, nginx:alpine) and dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  📤 Step 5: Pushing to DockerHub
&lt;/h2&gt;

&lt;p&gt;Once the image is scanned, the pipeline pushes it to DockerHub.&lt;br&gt;
If something fails in the pipeline, you can also push manually:..&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker tag gallery-app:latest your-dockerhub-username/gallery-app:latest
docker push your-dockerhub-username/gallery-app:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🌍 Step 6: Deploying on EC2....
&lt;/h2&gt;

&lt;p&gt;Finally, we deploy on our EC2 server.&lt;br&gt;
If the pipeline succeeds, this is automatic.&lt;br&gt;
If not, you can also do it manually:..&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker pull your-dockerhub-username/gallery-app:latest
docker run -d -p 80:80 --name gallery-app-cont your-dockerhub-username/gallery-app:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Now, visit your EC2 public IP in the browser and your Gallery App is live..... 🚀&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Overall Flow
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Run locally (npm run dev)&lt;/li&gt;
&lt;li&gt;Build and serve with Docker&lt;/li&gt;
&lt;li&gt;Jenkins pipeline automates build → scan → push → deploy&lt;/li&gt;
&lt;li&gt;App runs on EC2, accessible on port 80&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🤝 Contributing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;If you like this project:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⭐ Star the repo&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🍴 Fork it and experiment&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🛠️ Contribute via pull requests&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thanks for supporting this project 💙&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 Follow Me for More Content
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/muhammadishaq-khan/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/muhammadiishaq" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔥 With this setup, you have not only built a cool Gallery App, but also learned how to apply DevOps practices (CI/CD, Docker, Scanning, Deployment) to make your app production-ready.&lt;/strong&gt;&lt;/p&gt;

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