DEV Community

Cover image for πŸš€ Building & Deploying My Next.js Portfolio with Docker, AWS, CI/CD and monitoring with Promithius and Grafana"
Ritesh Singh
Ritesh Singh

Posted on • Edited on

πŸš€ Building & Deploying My Next.js Portfolio with Docker, AWS, CI/CD and monitoring with Promithius and Grafana"

πŸš€ Next.js Portfolio – DevOps Ready

This is Personal Portfolio Project built with Next.js, containerized using Docker, deployed on AWS EC2 (Free Tier), and distributed globally via AWS CloudFront CDN.

The deployment pipeline is fully automated using GitHub Actions (CI/CD) β€” from building the Docker image to pushing it to Docker Hub and deploying it on EC2.

For performance and container health monitoring, the project integrates a Monitoring Stack using Prometheus, Grafana, and cAdvisor, all connected through a shared Docker network.

It demonstrates both frontend skills (React/Next.js) and DevOps practices (CI/CD, Docker, DockerHub ,aws ,cloudfront, promithius and grafana).

⚑ Workflow

DevOps Workflow


πŸ“Έ Screenshots

about

Homepage

skills

Homepage


✨ Features

  • βš›οΈ Modern portfolio built with Next.js (SSR + React 18).
  • πŸ“± Responsive design for desktop & mobile.
  • 🐳 Fully Dockerized (multi-stage build, production optimized).
  • ☁️ Deployed on AWS EC2 Free Tier.
  • πŸ”„ Automated CI/CD pipeline with GitHub Actions:
    • Runs tests (npm run build).
    • Builds and pushes Docker image to DockerHub.
    • SSH into EC2 and redeploys automatically.
  • πŸ“œ .

πŸ› οΈ Tech Stack

  • Frontend: Next.js, React, Tailwind CSS
  • Containerization: Docker, DockerHub
  • CI/CD: GitHub Actions
  • Cloud: AWS EC2 (Ubuntu 22.04, Free Tier)
  • IaC: Terraform

πŸ“‚ Project Structure

Homepage

πŸ’» Run Locally

Clone the repo:

git clone git@github.com:ritesh355/portfolio.git
cd portfolio
Enter fullscreen mode Exit fullscreen mode

Install dependencies:

npm install
Enter fullscreen mode Exit fullscreen mode

Run dev server:

npm run dev
Enter fullscreen mode Exit fullscreen mode

then visit http://localhost:3000


πŸ“¦ Docker Setup

Build the image:

docker build -t ritesh355/nextjs-portfolio:latest .
Enter fullscreen mode Exit fullscreen mode

run the container:

docker run -d -p 3000:3000 ritesh355/nextjs-portfolio:latest
Enter fullscreen mode Exit fullscreen mode

then visit http://localhost:3000


☁️ Deployment on AWS EC2

1.Launch Ubuntu EC2 Free Tier.
Homepage

2.after connetint that ec2 Install Docker:

sudo apt update && sudo apt install -y docker.io
sudo usermod -aG docker ubuntu
Enter fullscreen mode Exit fullscreen mode
  1. Pull and run image:
  docker pull ritesh355/nextjs-portfolio:latest
docker run -d -p 80:3000 ritesh355/nextjs-portfolio:latest
Enter fullscreen mode Exit fullscreen mode

4.Visit http://EC2-Public-IP


πŸ€– GitHub Actions CI/CD

Located in .github/workflows/main.yml:

  • Runs tests (npm run build).

  • Builds & pushes image to DockerHub.

  • SSH into EC2, pulls new image, restarts container.

Example Workflow

name: Build, Push & 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

Enter fullscreen mode Exit fullscreen mode

πŸ“Š Monitoring Stack

To monitor the Next.js portfolio container, I implemented a full container monitoring setup using Prometheus, Grafana, and cAdvisor.

Steps Implemented

  1. Run cAdvisor container to collect metrics:
docker run -d \
  --name=cadvisor \
  --network=monitoring \
  -p 8080:8080 \
  -v /:/rootfs:ro \
  -v /var/run:/var/run:ro \
  -v /sys:/sys:ro \
  -v /var/lib/docker/:/var/lib/docker:ro \
  gcr.io/cadvisor/cadvisor:v0.47.2
Enter fullscreen mode Exit fullscreen mode

  1. Run Prometheus container with cAdvisor target:
docker run -d \
  --name=prometheus \
  --network=monitoring \
  -p 9090:9090 \
  -v /etc/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml \
  prom/prometheus
Enter fullscreen mode Exit fullscreen mode

  1. Prometheus configuration (/etc/prometheus/prometheus.yml):
global:
  scrape_interval: 5s

scrape_configs:
  - job_name: 'cadvisor'
    static_configs:
      - targets: ['cadvisor:8080']

Enter fullscreen mode Exit fullscreen mode

  1. Run Grafana container
docker run -d \
  --name=grafana \
  --network=monitoring \
  -p 3001:3000 \
  grafana/grafana

Enter fullscreen mode Exit fullscreen mode

πŸ‘¨β€πŸ’» Author

Ritesh Singh

🌐 LinkedIn |
πŸ“ Hashnode |
πŸ’»GitHub


⚑ Built with ❀️ using Next.js + Docker + AWS + DevOps

Top comments (0)