A production-grade(ish) microservice demo you can actually run:
- Auth Service (Node/Express, JWT) — register, login,
GET /me
- Notes Service (Node/Express) — CRUD notes (per user)
- Postgres (StatefulSet + PVC) — persistent storage
- Web (Nginx + React/Vite/Tailwind) — SPA UI, reverse-proxies
/api/*
to backend services - Kubernetes — independent scaling per service + HPAs, ConfigMaps/Secrets, health checks
- Docker — one image per service; push to Docker Hub before deploying
Architecture patterns: API Gateway (Nginx), Externalized Config (K8s Secrets/ConfigMaps), 12‑Factor apps, Immutable images, Horizontal scaling with Deployments + HPAs, Persistent DB via StatefulSet+PVC.
Requirements: Docker Desktop (with Kubernetes) or Minikube, plus kubectl
and kustomize
(or kubectl kustomize
).
-
Build & push images (replace
<your-dockerhub-username>
first):
PowerShell:cd scripts .\build_and_push.ps1 -DockerHubUser "<your-dockerhub-username>"
Bash:
cd scripts ./build_and_push.sh <your-dockerhub-username>
-
Create namespace + secrets:
kubectl apply -f k8s/namespace.yaml kubectl apply -f k8s/secrets.yaml
-
Deploy Postgres first, then services + web:
kubectl apply -f k8s/postgres-statefulset.yaml kubectl apply -k k8s
-
Expose externally:
- If you're on Docker Desktop with Kubernetes, the
web
Service istype: LoadBalancer
. Get the URL:kubectl get svc -n notes-app
- If you're on Minikube, use:
minikube service web -n notes-app
- If you're on Docker Desktop with Kubernetes, the
-
Login details: Register a user in the UI (or via API) and start adding notes.
Each service can run locally too:
# Terminal 1: Postgres in Docker (dev only)
docker run --name notes-pg -e POSTGRES_DB=notesdb -e POSTGRES_USER=notesuser -e POSTGRES_PASSWORD=notespass -p 5432:5432 -d postgres:16-alpine
# Terminal 2: Auth service
cd services/auth
npm ci
set DB_HOST=127.0.0.1 && set DB_USER=notesuser && set DB_PASSWORD=notespass && set DB_NAME=notesdb && set JWT_SECRET=devsecret && set PORT=4000 && npm start
# Terminal 3: Notes service
cd services/notes
npm ci
set DB_HOST=127.0.0.1 && set DB_USER=notesuser && set DB_PASSWORD=notespass && set DB_NAME=notesdb && set JWT_SECRET=devsecret && set PORT=5000 && npm start
# Terminal 4: Web (frontend dev server)
cd frontend
npm ci
npm run dev
Then visit the dev UI (Vite) on the printed port (usually 5173). In frontend/src/lib/api.js
, set const API_BASE = "http://localhost:8080"
if you run the Nginx gateway locally; otherwise point the UI directly to the services (http://localhost:4000
and :5000
) and enable CORS on both.
POST /api/auth/register
{ name, email, password }
POST /api/auth/login
{ email, password }
→{ token }
GET /api/auth/me
(Bearer token) → user profile
GET /api/notes
→ list your notesPOST /api/notes
{ title, content }
GET /api/notes/:id
PUT /api/notes/:id
{ title, content }
DELETE /api/notes/:id
All services expose GET /healthz
for probes.
- Independently scalable:
Deployment
per microservice +HorizontalPodAutoscaler
forauth
andnotes
- Persistent DB:
StatefulSet
+PersistentVolumeClaim
- Secrets: JWT secret, DB creds
- Config: Minimal via env; 12‑factor ready
- External Access:
web
service isLoadBalancer
(orNodePort
if your cluster doesn’t support LB), serving the SPA and proxying/api/*
to auth/notes - Observability: basic logs + health endpoints
- JWT auth, BCrypt password hashing, Helmet headers
- Secrets in K8s
Secret
objects (avoid committing real secrets) - Nginx only proxies
/api/*
; static files served safely; no wildcard upstreams - Network policies are omitted for brevity—add them in real deployments
- HTTPS termination recommended at ingress/cloud LB level
- Software + what it does: You’re reading it. A Notes app with login/registration and per‑user CRUD notes.
- Architecture design: See
docs/ARCHITECTURE.md
. - Benefits/challenges: See
docs/ARCHITECTURE.md
. - Config management repo: Use this folder as your git repo root.
- Video: Record 5–10 minutes following
docs/DEMO_SCRIPT.md
.
MIT