This project is a student registration system built with Flask and MySQL. It allows users to register students through a web form and view all registered students. The project will be deployed in two phases:
- Monolithic Architecture on an EC2 instance using Ubuntu.
- Microservices Architecture, containerized with Docker and orchestrated using Kubernetes, deployed via CI/CD pipelines.
- Register students through a web form (
register.html) - View all registered students (
student.html) - Data stored in a MySQL database
- Built using Flask (Python)
- Initially deployed as a monolithic application
- Later transitioned to microservices (
docker-compose.yml&Dockerfile) and lastly deployed on Kubernetes cluster (manifest files), using CI/CD
- Use Ubuntu AMI
sudo apt update
python3 --version # Check if Python is installed
sudo apt install python3.12-venv -ymkdir pyapp
cd pyapp
git init
git pull https://github.com/harshkhalkar/student-registration-flask-application.gitUse only the following files for now:
app.pyrequirements.txttemplates/register.htmltemplates/student.htmlIgnore other files likeDockerfile,docker-compose.ymland else for now.
sudo apt install mysql-server -y
sudo mysql_secure_installationLogin to MySQL:
sudo mysqlRun the following to configure root user and initialize database:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_new_password';
FLUSH PRIVILEGES;
EXIT;Then:
mysql -u root -p < init.sqlOr run the SQL manually (see init.sql content below).
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python app.pyVisit: http://public-ip:5000
.
├── app.py
├── requirements.txt
├── init.sql
└── templates
├── register.html
└── student.htmlCREATE DATABASE IF NOT EXISTS studentsdb;
USE studentsdb;
CREATE TABLE IF NOT EXISTS students (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) NOT NULL UNIQUE,
course VARCHAR(100) NOT NULL,
address VARCHAR(100) NOT NULL,
phone VARCHAR(100) NOT NULL,
contact VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);.
├── app.py
├── Dockerfile
├── docker-compose.yml
├── init.sql
├── requirements.txt
├── templates/
│ ├── register.html
│ └── student.html
├── tests/
│ ├── __init__.py
│ └── test_app.pyFlask==2.3.2
mysql-connector-python
Werkzeug<3.0.0Create a tests directory:
mkdir tests
touch tests/__init__.pyimport unittest
from app import app
class FlaskTestCase(unittest.TestCase):
def setUp(self):
self.app = app.test_client()
def test_home_status_code(self):
response = self.app.get('/')
self.assertEqual(response.status_code, 200)
if __name__ == '__main__':
unittest.main()
pipeline {
agent any
environment {
REPO_URL = 'https://github.com/harshkhalkar/student-registration-flask-application.git'
BRANCH = '*/main'
REMOTE_USER = 'ubuntu'
REMOTE_HOST = '54.224.69.173'
REMOTE_DIR = '/pyapp'
}
stages {
stage('Clone Repository') {
steps {
echo 'Cloning repository...'
checkout([
$class: 'GitSCM',
branches: [[name: "${BRANCH}"]],
userRemoteConfigs: [[url: "${REPO_URL}"]]
])
}
}
stage('Install Docker & Compose') {
steps {
echo 'Installing Docker & Docker Compose (if not already installed)...'
sh '''
if ! command -v docker &> /dev/null; then
sudo apt update -y
sudo apt install -y docker.io
sudo systemctl start docker
fi
if ! command -v docker-compose &> /dev/null; then
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" \
-o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
fi
docker --version
docker-compose --version
'''
}
}
stage('Build Containers') {
steps {
echo 'Starting containers with Docker Compose...'
sh 'sudo docker-compose up -d --build'
}
}
stage('Run Tests') {
steps {
echo 'Running tests inside container...'
sh '''
sudo docker ps
curl -s localhost:5000 || echo "Flask app not reachable"
sudo docker exec pyapp ls -l
sudo docker exec pyapp ls -l tests
sudo docker exec pyapp python3 -m unittest discover -s tests -t .
'''
}
}
stage('Cleanup Local') {
steps {
echo 'Cleaning up Docker containers and images...'
sh '''
sudo docker-compose down --volumes --remove-orphans
sudo docker image prune -f
IMAGES=$(sudo docker images -q)
if [ -n "$IMAGES" ]; then
sudo docker rmi -f $IMAGES || true
else
echo "No images to remove"
fi
'''
}
}
stage('Deploy to Remote') {
steps {
echo 'Deploying to remote server...'
script {
sshagent(['5db86cd4-3324-4473-bf9b-f2f9f5e397d6']) {
sh """
ssh -o StrictHostKeyChecking=no ${REMOTE_USER}@${REMOTE_HOST} << 'ENDSSH'
set -e
echo 'Installing Docker on remote server...'
if ! command -v docker &> /dev/null; then
sudo apt update -y
sudo apt install -y docker.io
sudo systemctl start docker
fi
if ! command -v docker-compose &> /dev/null; then
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-\\\$(uname -s)-\\\$(uname -m)" \
-o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
fi
echo 'Preparing deployment directory...'
mkdir -p ${REMOTE_DIR}
cd ${REMOTE_DIR}
if [ ! -d .git ]; then
git init
git remote add origin ${REPO_URL}
fi
git fetch origin
git reset --hard origin/main
echo 'Starting app...'
rm -rf kubernetes LICENSE
sudo docker-compose up -d --build
ENDSSH
"""
}
}
}
}
}
}
-
Install Jenkins and Access Dashboard
-
Install Plugins:
- SSH Agent
-
Add Credentials:
- Type: SSH Username with Private Key
-
Configure Project:
- Create new item → Pipeline
- Set GitHub webhook trigger
- Use inline pipeline script or Jenkinsfile from repo. Use inline pipeline script or Jenkinsfile from repo
-
Allow Jenkins to use sudo Docker (on both Jenkins & EC2 Live Server):
Run:
sudo visudo
add:
jenkins ALL=(ALL) NOPASSWD: /usr/bin/apt, /usr/bin/docker, /usr/bin/docker-compose
or:
sudo usermod -aG docker jenkins
sudo visudo
jenkins ALL=(ALL) NOPASSWD: /usr/bin/apt, /usr/bin/kubectl
pipeline {
agent any
environment {
IMAGE_NAME = "harshkhalkar/pyapp"
IMAGE_TAG = "v1"
}
stages {
stage('Cloning Repo') {
steps {
echo 'Cloning Repository...'
checkout([$class: 'GitSCM',
branches: [[name: '*/main']],
userRemoteConfigs: [[url: 'https://github.com/harshkhalkar/student-registration-flask-application.git']]
])
}
}
stage('Build Docker Image') {
steps {
echo 'Building Docker Image...'
sh "docker build -t ${IMAGE_NAME}:${IMAGE_TAG} ."
}
}
stage('Push to Docker Hub') {
steps {
withCredentials([usernamePassword(credentialsId: 'dockerhub-creds', usernameVariable: 'DOCKER_USER', passwordVariable: 'DOCKER_PASS')]) {
sh 'echo $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin'
sh "docker push ${IMAGE_NAME}:${IMAGE_TAG}"
}
}
}
stage('Deploy to Kubernetes') {
steps {
sshagent(['5db86cd4-3324-4473-bf9b-f2f9f5e397d6']) {
sh '''
ssh -o StrictHostKeyChecking=no ubuntu@<K8S_MASTER_PUBLIC_IP> << 'ENDSSH'
mkdir -p /k8s
cd /k8s
git init
git pull https://github.com/harshkhalkar/student-registration-flask-application.git
cd kubernetes
kubectl apply -f mysql-configmap.yaml
kubectl apply -f mysql-deployment.yaml
kubectl apply -f mysql-service.yaml
kubectl apply -f pyapp-deployment.yaml
kubectl apply -f pyapp-service.yaml
kubectl get pods
kubectl get svc
ENDSSH
'''
}
}
}
}
}
https://github.com/harshkhalkar/jenkins.git