Payments-Case Study

Arnab SahaArnab Saha
4 min read

Tech Stack

  • Frontend: React + Vite + TailwindCSS

  • Backend: Node.js + Express

  • Database: MongoDB (both Atlas and local via Docker)

Step 1: Vite Config (Frontend)

Update your Vite config file to support aliasing, Tailwind, and preview hosting:

import path from "path"
import tailwindcss from "@tailwindcss/vite"
import react from "@vitejs/plugin-react"
import { defineConfig } from "vite"

export default defineConfig({
  plugins: [react(), tailwindcss()],
    server: {
    host: true,
    port: 5173
  },
  preview: {
    host: true,
    port: 4173,
    allowedHosts: ['payments.grevelops.co'],
  },
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
    },
  },
})

Docker Setup (Without Local MongoDB)

  1. Backend Dockerfile (backend/Dockerfile.prod)
FROM node:22-alpine

WORKDIR /Payments

COPY package*.json ./

RUN npm install

# Install ts-node globally
RUN npm install -g ts-node
RUN npm install typescript --save-dev
COPY . .

# Build the project during image creation
RUN npm run build

ENV PORT=3000
EXPOSE 3000

# Start the app when container runs
CMD [ "npm", "start" ]
docker build --platform linux/amd64 -f Dockerfile.prod -t hparnab/payments-backend:latest .

docker login

docker push hparnab/payments-backend:latest
  1. Frontend Dockerfile (frontend/Dockerfile.prod)
FROM node:22-alpine

WORKDIR /Payments

COPY package*.json ./
RUN npm install

# ๐Ÿ‘‡ Accept and inject build-time variable
ARG VITE_API_URL
ENV VITE_API_URL=$VITE_API_URL

COPY . .

RUN npm run build

ENV PORT=4173
EXPOSE 4173

CMD ["npm", "run", "preview"]
docker build --platform linux/amd64 -f Dockerfile.prod --build-arg VITE_API_URL=https://paymentss.grevelops.co/api/v1 -t hparnab/payments-frontend:latest .

docker login

docker push hparnab/payments-frontend:latest
  1. Docker Compose (With MongoDB Atlas)
//docker-compose.yaml

version: "3.9"

services:
  backend:
    image: hparnab/payments-backend:latest
    platform: linux/amd64
    ports:
      - "3000:3000"
    restart: unless-stopped
    environment:
      - NODE_ENV=production
      - JWT_SECRET_KEY="<secrectkey>"
      - MONGO_URL=mongodb+srv://<url it should not be in quotes>
      - CORS_ORIGIN=https://payments.grevelops.co

  frontend:
    image: hparnab/payments-frontend:latest
    platform: linux/amd64
    ports:
      - "4173:4173"
    restart: unless-stopped

Local MongoDB Setup (for Educational Purposes)

Note: MongoDB transactions require replica sets, which aren't supported in this setup. Use for basic dev/testing only โ€” not production-ready if transactions are critical.

version: "3.9"

services:
  mongodb:
    image: mongo:6.0  # or any stable mongo version you want
    platform: linux/amd64
    ports:
      - "27017:27017"  # expose default mongo port to host
    volumes:
      - mongo-data:/data/db  # persist data locally

  backend:
    image: hparnab/payments-backend:latest
    platform: linux/amd64
    ports:
      - "3000:3000"
    restart: unless-stopped
    environment:
      - NODE_ENV=production
      - JWT_SECRET_KEY="jsonwebtokensecretkeyofarnab"
      - MONGO_URL=mongodb://mongodb:27017/yourdbname  # point to local mongo service by container name
      - CORS_ORIGIN=https://payments.grevelops.co
    depends_on:
      - mongodb

  frontend:
    image: hparnab/payments-frontend:latest
    platform: linux/amd64
    ports:
      - "4173:4173"
    restart: unless-stopped

volumes:
  mongo-data:

Summary

  • Vite config supports Tailwind, aliasing, and external preview hosting.

  • Separate Dockerfile.prod used for backend and frontend builds.

  • MongoDB Atlas preferred for production due to transaction support.

  • Local MongoDB via Docker useful for testing, but not suitable for transaction-based operations.

Deployment

Make Azure VM

  1. Create an Azure Virtual Machine with:

    • Ubuntu 24.04 LTS

    • Enabled HTTPS, SSH, and HTTP during setup.

  2. Add an RSA SSH key during the VM setup process.

  3. Download the .pem file for secure access.

  4. Go to Networking > Inbound Port Rules and add the required ports (e.g., 3000, 3001, 3002, etc.).

  5. Set appropriate permissions on your .pem file:

     chmod 600 /Users/thearnabsaha/Downloads/keys/vm1_key.pem
    
  6. Connect to your VM via SSH:

     ssh -i "/Users/thearnabsaha/Downloads/keys/vm1_key.pem" azureuser@40.81.235.53
    

Nginx Config

  1. sudo apt update

  2. sudo apt install nginx

  3. sudo rm -rf /etc/nginx/nginx.conf

  4. sudo nano /etc/nginx/nginx.conf

events {}

http {
    server {
        listen 80;
        server_name paymentss.grevelops.co;

        location / {
            proxy_pass <http://localhost:3000>;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }
    }

    server {
        listen 80;
        server_name payments.grevelops.co;

        location / {
            proxy_pass <http://localhost:4173>;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }
    }
}
  1. sudo systemctl restart nginx

SSL certificate

  1. sudo apt install certbot python3-certbot-nginx

  2. sudo certbot --nginx

  3. sudo nginx -t

  4. sudo nginx -s reload


Docker Installation

sudo apt update && sudo apt upgrade -y

sudo apt install -y ca-certificates curl gnupg lsb-release

sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

//to check docker
docker --version

//to run docker
sudo systemctl enable docker
sudo systemctl start docker

//to run without the sudo command
sudo usermod -aG docker $USER
newgrp docker

docker compose version

sudo docker compose up --pull always

sudo docker compose up -d

sudo docker compose pull
sudo docker compose up --force-recreate
0
Subscribe to my newsletter

Read articles from Arnab Saha directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Arnab Saha
Arnab Saha