Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Git
.git
.gitignore

# IDE
.vscode
.idea
*.swp
*.swo

# Build
target
*.class
*.jar
*.war

# Maven
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/MavenWrapperDownloader.java

# OS
.DS_Store
Thumbs.db

# Docker
Dockerfile
docker-compose.yml
.dockerignore

# Documentation
README.md
LICENSE
screenshots/

# Node/npm (if applicable)
node_modules
npm-debug.log
50 changes: 34 additions & 16 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,22 +1,40 @@
# Build stage
FROM eclipse-temurin:21-jdk-alpine AS build
WORKDIR /app
COPY . .
RUN chmod +x mvnw && ./mvnw clean package -DskipTests -B
# # get the base image for Java
# FROM eclipse-temurin:21-jdk-jammy

# Run stage - alpine has significantly fewer CVEs than ubuntu/jammy
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
# #code in a working directory
# WORKDIR /app

# #copy all the src code to the container
# COPY . .

# # install the libraries with maven
# RUN chmod +x mvnw && ./mvnw clean package -DskipTests -B

# Pull latest security patches for OS libraries
RUN apk update && apk upgrade --no-cache
# #Expose the port that the application will run on
# EXPOSE 8080

# Create a non-root user for security (Alpine uses addgroup/adduser instead of groupadd/useradd)
RUN addgroup -S devsecops && adduser -S -G devsecops devsecops
USER devsecops
# # run the application
# # CMD ["java", "-jar", "target/*.jar"]
# ENTRYPOINT ["sh", "-c", "java -jar target/*.jar"]

# Copy only the built artifact
COPY --from=build /app/target/*.jar app.jar

# Stage 1: Build
FROM eclipse-temurin:21-jdk-jammy AS builder
WORKDIR /app
COPY pom.xml ./
COPY .mvn ./.mvn
COPY mvnw ./
RUN dos2unix mvnw || sed -i 's/\r$//' mvnw
RUN chmod +x mvnw && ./mvnw dependency:resolve
COPY src ./src
RUN ./mvnw clean package -DskipTests -B

# Stage 2: Runtime
FROM eclipse-temurin:21-jre-jammy
WORKDIR /app
RUN groupadd -r appuser && useradd -r -g appuser appuser
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 CMD java -cp app.jar org.springframework.boot.loader.JarLauncher || exit 1
USER appuser
ENTRYPOINT ["java", "-jar", "app.jar"]
67 changes: 18 additions & 49 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,53 +1,23 @@
#docker build and run the application using docker-compose
services:
mysql:
image: mysql:8.0
container_name: bankapp-mysql
image: mysql:latest
container_name: mysql
environment:
MYSQL_ROOT_PASSWORD: Test@123
MYSQL_DATABASE: bankappdb
ports:
- "3306:3306"
volumes:
- mysql-data:/var/lib/mysql
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: bankapp
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-pTest@123"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
networks:
- bankapp-net

ollama:
image: ollama/ollama
container_name: bankapp-ollama
ports:
- "11434:11434"
volumes:
- ollama-data:/root/.ollama
healthcheck:
test: ["CMD", "ollama", "list"]
interval: 10s
timeout: 5s
retries: 5
networks:
- bankapp-net

ollama-pull-model:
image: ollama/ollama
container_name: ollama-pull-model
environment:
- OLLAMA_HOST=ollama
- "3306:3306"
volumes:
- ollama-data:/root/.ollama
depends_on:
ollama:
condition: service_healthy
entrypoint: /bin/sh
command: -c "ollama pull tinyllama"
- mysql_data:/var/lib/mysql
networks:
- bankapp-net

- bankapp_network
bankapp:
build: .
container_name: bankapp
Expand All @@ -56,22 +26,21 @@ services:
environment:
MYSQL_HOST: mysql
MYSQL_PORT: 3306
MYSQL_DATABASE: bankappdb
MYSQL_DATABASE: bankapp
MYSQL_USER: root
MYSQL_PASSWORD: Test@123
OLLAMA_URL: http://ollama:11434
depends_on:
mysql:
condition: service_healthy
ollama-pull-model:
condition: service_completed_successfully
networks:
- bankapp-net
- bankapp_network

#docker network create
networks:
bankapp_network:
driver: bridge

#docker volume create
volumes:
mysql-data:
ollama-data:
mysql_data:

networks:
bankapp-net:
driver: bridge
78 changes: 78 additions & 0 deletions k8s/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Kubernetes Deployment (Step-by-Step)

This guide deploys the app stack (`bankapp` + `mysql` + `ollama`) into a local Kind cluster.

## 0) Prerequisites

- Docker running
- `kubectl` installed
- `kind` installed

## 1) Build application image

```bash
docker build -t santoshpathak7456/ai-bankapp-devops_bankapp:k8s .
```

## 2) Create Kind cluster

```bash
kind create cluster --config setup-k8s/kind-config.yml
```

## 3) Load local image into Kind

```bash
kind load docker-image santoshpathak7456/ai-bankapp-devops_bankapp:k8s --name tws-cluster
```

## 4) Install metrics-server (required for HPA)

```bash
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
kubectl patch deployment metrics-server -n kube-system --type='json' -p='[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--kubelet-insecure-tls"}]'
kubectl rollout status deployment/metrics-server -n kube-system --timeout=120s
```

## 5) Apply manifests in order

```bash
kubectl apply -f k8s/namespace.yaml
kubectl apply -f k8s/configMap.yaml
kubectl apply -f k8s/secrets.yaml
kubectl apply -f k8s/persistentVolume.yaml
kubectl apply -f k8s/pvc.yaml
kubectl apply -f k8s/mysql-deployment.yaml
kubectl apply -f k8s/ollama-deployment.yaml
kubectl apply -f k8s/bankapp-deployment.yaml
kubectl apply -f k8s/service.yaml
kubectl apply -f k8s/hpa.yaml
```

## 6) Verify deployment

```bash
kubectl get all -n bankapp
kubectl get pvc,pv -n bankapp
kubectl get hpa -n bankapp
kubectl top pods -n bankapp
```

## 7) Access application

Kind config maps node port `30080` to host `8080`.

- Open: `http://localhost:8080`

## 8) Test autoscaling

```bash
kubectl run load-test --image=busybox:1.36 -n bankapp -- sh -c "while true; do wget -q -O- http://bankapp-service:8080/actuator/health >/dev/null 2>&1; done"
kubectl get hpa -n bankapp -w
```

Cleanup load pod:

```bash
kubectl delete pod load-test -n bankapp
```
111 changes: 111 additions & 0 deletions k8s/bankapp-deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# `apiVersion` apps/v1 use hota hai deployments manage karne ke liye.
apiVersion: apps/v1
# `kind` is object ko Deployment define karta hai.
kind: Deployment
# `metadata` deployment ka naam, namespace aur labels rakhta hai.
metadata:
# Bank application deployment ka unique naam.
name: bankapp-deployment
# App resources ko bankapp namespace me isolate karta hai.
namespace: bankapp
# `labels` se logical grouping aur selection easy hota hai.
labels:
# App tier ko identify karne wala label.
app: bankapp
# `spec` desired number of pods aur pod template batata hai.
spec:
# 3 replicas high availability/load sharing ke basic use-case ke liye.
replicas: 3
# `selector` batata hai deployment kin pods ko own karega.
selector:
matchLabels:
# Ye selector template label se match hona mandatory hai.
app: bankapp
# `template` naye pods ka exact blueprint provide karta hai.
template:
metadata:
labels:
# Service/deployment matching ke liye pod label.
app: bankapp
spec:
# Pod ke containers yahan define hote hain.
containers:
# Main bankapp container configuration.
- name: bankapp
# Docker image jisse application run hogi.
image: santoshpathak7456/ai-bankapp-devops_bankapp:k8s
# Container exposed ports list.
ports:
# Spring Boot default HTTP port 8080 par listen karta hai.
- containerPort: 8080
# Runtime environment variables inject karne ka section.
env:
# App ka target database naam.
- name: MYSQL_DATABASE
valueFrom:
# Non-secret config ConfigMap se lena safe/maintainable hota hai.
configMapKeyRef:
# Source ConfigMap ka naam.
name: bankapp-config-map
# Required key jiska value env var banega.
key: MYSQL_DATABASE
# DB host jahan app connect karegi.
- name: MYSQL_HOST
valueFrom:
configMapKeyRef:
# Same central ConfigMap reuse karke config centralized rakhi gayi hai.
name: bankapp-config-map
# MySQL service name wali key.
key: MYSQL_HOST
# DB port app ko dynamic tarike se dene ke liye env var.
- name: MYSQL_PORT
valueFrom:
configMapKeyRef:
# ConfigMap source name.
name: bankapp-config-map
# Port key value.
key: MYSQL_PORT
# DB username jisse app authenticate karegi.
- name: MYSQL_USER
valueFrom:
configMapKeyRef:
# ConfigMap reference for username.
name: bankapp-config-map
# User key fetch hoti hai.
key: MYSQL_USER
# Root password sensitive hai isliye Secret se inject hota hai.
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
# Secret resource ka naam.
name: bankapp-secret
# App DB password secret key.
key: MYSQL_PASSWORD
# Ollama endpoint centralized config se inject hota hai.
- name: OLLAMA_URL
valueFrom:
configMapKeyRef:
name: bankapp-config-map
key: OLLAMA_URL
# HPA ko work karane ke liye CPU/memory requests required hote hain.
resources:
requests:
cpu: "100m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
# Pod ready tab mark ho jab actuator health pass kare.
readinessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
# Liveness check unhealthy pod ko restart karne me help karti hai.
livenessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 60
periodSeconds: 20
Loading