This project is a fullstack application deployed using:
- Frontend (React / Vite)
- Backend (Node.js / Express)
- Database (PostgreSQL)
- Docker (Containerization)
- GitHub Actions (CI/CD)
- AWS EC2 (Deployment Server)
The CI/CD pipeline automatically:
- Builds Docker images
- Pushes images to Docker Hub
- Connects to EC2 via SSH
- Pulls latest images
- Starts frontend, backend, and database containers
project-root/
│
├── frontend/
├── backend/
├── app-version/
│ ├── frontend.txt
│ └── backend.txt
│
├── .github/workflows/
│ └── deploy.yml
│
├── docker-compose.yml (optional)
└── README.md
Instead of using latest Docker tag, this project uses version files.
app-version/frontend.txt
app-version/backend.txt
frontend.txt → 1.0
backend.txt → 1.0
Updating these versions triggers a new deployment.
Go to:
GitHub → Repository → Settings → Secrets → Actions
Add the following:
| Secret Name | Description |
|---|---|
| DOCKER_USERNAME | Docker Hub username |
| DOCKER_TOKEN | Docker Hub access token |
| VITE_BACKEND_URL | Backend public URL |
| EC2_HOST | EC2 public IP |
| EC2_USER | EC2 username (ubuntu) |
| EC2_SSH_KEY | EC2 private SSH key |
| DB_HOST | Database host (mydb) |
| DB_USER | Database username |
| DB_PASSWORD | Database password |
| DB_NAME | Database name |
| JWT_SECRET | JWT secret key |
The GitHub Actions workflow performs:
- Checkout repository
- Read frontend & backend version
- Login to Docker Hub
- Build frontend Docker image
- Build backend Docker image
- Push images to Docker Hub
- SSH into EC2 server
- Pull new images
- Stop old containers
- Start database container
- Start backend container
- Start frontend container
User Browser
↓
Frontend Container (Port 3000)
↓
Backend Container (Port 5000)
↓
PostgreSQL Container (Port 5432)
All containers run inside Docker network:
fullstack-net
| Service | Hostname |
|---|---|
| Database | mydb |
| Backend | backend |
| Frontend | frontend |
DB_HOST=mydb
DB_USER=postgres
DB_PASSWORD=******
DB_NAME=mydb
DB_PORT=5432
PORT=5000
JWT_SECRET=******
VITE_BACKEND_URL=http://EC2_PUBLIC_IP:5000
app-version/frontend.txt
app-version/backend.txt
Example:
1.1
git add .
git commit -m "Deploy new version"
git push origin main
Pipeline will:
- Build images
- Push to Docker Hub
- Deploy to EC2
- Restart containers
sudo docker ps
sudo docker logs backend
sudo docker logs frontend
sudo docker logs mydb
sudo docker exec -it backend sh
sudo docker exec -it mydb psql -U postgres -d mydb
sudo docker network inspect fullstack-net
| Service | URL |
|---|---|
| Frontend | http://EC2_IP:3000 |
| Backend | http://EC2_IP:5000 |
| Database | Port 5432 |
Example:
- users
- posts
Check tables:
sudo docker exec -it mydb psql -U postgres -d mydb -c "\dt"
Ensure:
DB_HOST=mydb
Check:
VITE_BACKEND_URL
Ensure server runs on:
app.listen(5000, "0.0.0.0")
- React / Vite
- Node.js / Express
- PostgreSQL
- Docker
- GitHub Actions
- AWS EC2
- Docker Hub
- CI/CD Pipeline
Developer Push → GitHub
↓
GitHub Actions Build Docker Images
↓
Push Images to Docker Hub
↓
SSH into EC2
↓
Pull New Images
↓
Start Database
↓
Start Backend
↓
Start Frontend
↓
Application Live


