Payments-Case Study

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)
- 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
- 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
- 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
Create an Azure Virtual Machine with:
Ubuntu 24.04 LTS
Enabled HTTPS, SSH, and HTTP during setup.
Add an RSA SSH key during the VM setup process.
Download the
.pem
file for secure access.Go to Networking > Inbound Port Rules and add the required ports (e.g.,
3000
,3001
,3002
, etc.).Set appropriate permissions on your
.pem
file:chmod 600 /Users/thearnabsaha/Downloads/keys/vm1_key.pem
Connect to your VM via SSH:
ssh -i "/Users/thearnabsaha/Downloads/keys/vm1_key.pem" azureuser@40.81.235.53
Nginx Config
sudo apt update
sudo apt install nginx
sudo rm -rf /etc/nginx/nginx.conf
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;
}
}
}
- sudo systemctl restart nginx
SSL certificate
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx
sudo nginx -t
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
Subscribe to my newsletter
Read articles from Arnab Saha directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
