A full-stack Job Portal System built with microservices architecture, connecting employers and job seekers on a single platform. Backend REST APIs developed with Spring Boot (Java), frontend with React + TypeScript, containerized with Docker, orchestrated with Kubernetes, and monitored with Prometheus + Grafana.
This project implements a scalable recruitment platform where employers can post jobs, manage applications, and review candidates, while job seekers can search for jobs and apply directly. The system uses a microservices architecture deployed on Linux with Docker and Kubernetes.
job-portal/
βββ user-service/ # Spring Boot - User management & auth
β βββ src/
β βββ Dockerfile
β βββ pom.xml
βββ job-service/ # Spring Boot - Job listings CRUD
β βββ src/
β βββ Dockerfile
β βββ pom.xml
βββ application-service/ # Spring Boot - Application tracking
β βββ src/
β βββ Dockerfile
β βββ pom.xml
βββ Frontend/ # React + TypeScript SPA
β βββ src/
β βββ Dockerfile
β βββ nginx.conf
βββ k8s/ # Kubernetes manifests
β βββ namespace.yaml
β βββ config-and-secrets.yaml
β βββ persistent-volumes.yaml
β βββ users-db.yaml
β βββ jobs-db.yaml
β βββ applications-db.yaml
β βββ user-service.yaml
β βββ job-service.yaml
β βββ application-service.yaml
β βββ frontend.yaml
β βββ ingress.yaml
β βββ deploy.sh
βββ prometheus.yml # Prometheus scrape config
βββ docker-compose.yml # Base compose config
βββ docker-compose.dev.yml # Development environment
βββ docker-compose.test.yml # Testing environment
βββ docker-compose.prod.yml # Production environment
- Docker Engine / Docker Desktop
- Java 17+
- Maven 3.9+
- Node.js 20+
- kubectl + Minikube (for Kubernetes)
| Layer | Technology | Version |
|---|---|---|
| Frontend | React + TypeScript + Vite | React 18 |
| Backend | Spring Boot (Java) | 3.2.5 |
| Database | PostgreSQL | 15 |
| Containerization | Docker + Docker Compose | Latest |
| Orchestration | Kubernetes (Minikube) | Latest |
| Monitoring | Prometheus + Grafana | Latest |
| Styling | Tailwind CSS | 3.x |
- Register as Job Seeker or Employer
- Login with role-based access control
- Profile management
- Employers can post, update, and delete jobs
- Job Seekers can search by title, company, location, and type
- Filter by: FULL_TIME, PART_TIME, CONTRACT, INTERNSHIP
- Job Seekers apply with cover letters
- Employers manage applications per job
- Status flow: PENDING β REVIEWED β ACCEPTED / REJECTED
- Development, Testing, and Production environments
- All three can run simultaneously on the same machine
- Docker Compose layering (base + overrides)
- Deployments with 2 replicas per service
- StatefulSets for databases with PersistentVolumes
- Ingress for unified traffic routing
- ConfigMaps and Secrets for configuration
- Prometheus scrapes metrics every 15 seconds
- Spring Boot Actuator exposes
/actuator/prometheus - Grafana dashboards for JVM, HTTP, and DB metrics
docker compose -p dev -f docker-compose.yml -f docker-compose.dev.yml up --build# Terminal 1 - Development
docker compose -p dev -f docker-compose.yml -f docker-compose.dev.yml up
# Terminal 2 - Testing
docker compose -p test -f docker-compose.yml -f docker-compose.test.yml up
# Terminal 3 - Production
docker compose -p prod -f docker-compose.yml -f docker-compose.prod.yml up -d# Build and load images into Minikube
docker build -t job-portal/user-service:1.0.0 ./user-service
docker build -t job-portal/job-service:1.0.0 ./job-service
docker build -t job-portal/application-service:1.0.0 ./application-service
docker build -t job-portal/frontend:1.0.0 ./Frontend
minikube image load job-portal/user-service:1.0.0
minikube image load job-portal/job-service:1.0.0
minikube image load job-portal/application-service:1.0.0
minikube image load job-portal/frontend:1.0.0
# Apply all manifests
cd k8s && bash deploy.sh| Service | URL | Credentials |
|---|---|---|
| Frontend | http://localhost:3000 | Register to login |
| User API | http://localhost:8081 | β |
| Job API | http://localhost:8082 | β |
| Application API | http://localhost:8083 | β |
| Prometheus | http://localhost:9090 | No login |
| Grafana | http://localhost:3001 | admin / admin |
User Service (8081)
POST /api/users/register
POST /api/users/login
GET /api/users/{id}
PUT /api/users/{id}
Job Service (8082)
POST /api/jobs
GET /api/jobs
GET /api/jobs/{id}
PUT /api/jobs/{id}
DELETE /api/jobs/{id}
GET /api/jobs/employer/{employerId}
Application Service (8083)
POST /api/applications
GET /api/applications/job/{jobId}
GET /api/applications/applicant/{applicantId}
PUT /api/applications/{id}/status
DELETE /api/applications/{id}
| Entity | Field | Description |
|---|---|---|
| User | id | UUID primary key |
| User | fullName | Full name |
| User | Unique email | |
| User | role | JOB_SEEKER or EMPLOYER |
| Job | title | Job title |
| Job | companyName | Company name |
| Job | location | Job location |
| Job | salary | Salary amount |
| Job | jobType | FULL_TIME / PART_TIME / CONTRACT / INTERNSHIP |
| Job | status | OPEN or CLOSED |
| Application | jobId | Reference to job |
| Application | applicantId | Reference to user |
| Application | coverLetter | Application cover letter |
| Application | status | PENDING / REVIEWED / ACCEPTED / REJECTED |
Each service has its own dedicated PostgreSQL database (database-per-service pattern). Services communicate over Docker's internal network. Nginx acts as a reverse proxy in the frontend container, routing API calls to the correct backend service.
Browser β Nginx (Frontend) β user-service β userdb
β job-service β jobdb
β app-service β applicationdb
Prometheus β /actuator/prometheus (all services)
Grafana β Prometheus
- Linux Deployment: Runs on Ubuntu (VMware). Add user to docker group to avoid sudo.
- AppArmor Fix: If containers fail to stop, run
sudo aa-remove-unknown - Data Persistence: Use
docker compose down(without-v) to keep database volumes - Multi-stage Dockerfiles: Final images use JRE-only Alpine for minimal size
- Non-root containers: All Spring Boot containers run as a dedicated non-root user
- Add a new service: Create a Spring Boot module, add Dockerfile, register in docker-compose.yml and k8s/
- Change ports: Update docker-compose.dev.yml port mappings
- Add Grafana dashboard: Import any dashboard ID from grafana.com/grafana/dashboards
- Scale a service: Update
replicasin the Kubernetes Deployment manifest
This project is open source. Feel free to use and modify as needed.
Omar Salama β Computer Science Student, Ain Shams University / University of East London
Habiba Fahd β Computer Science Student, Ain Shams University / University of East London
Eman Mohamed β Computer Science Student, Ain Shams University / University of East London
Maria Mark β Computer Science Student, Ain Shams University / University of East London
For issues, questions, or suggestions, please open an issue on GitHub.