Skip to content

Commit 7733c07

Browse files
committed
Update readme with k8s deployment instructions
1 parent b15ee63 commit 7733c07

1 file changed

Lines changed: 113 additions & 19 deletions

File tree

README.md

Lines changed: 113 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -81,20 +81,20 @@ With this we can able to:**
8181
pip freeze > requirements.txt
8282
```
8383

84-
## Project Local Setup
84+
## Project local setup
8585

86-
- **Install dependencies**
86+
**1. Install dependencies**
8787
```txt
8888
make install
8989
```
9090
- (or run pip install -r requirements.txt directly)
9191

92-
- **Run the App**
92+
**2. Run the App**
9393
```txt
9494
make run
9595
```
9696

97-
- **Flask app will start at:**
97+
**3. Flask app will start at:**
9898
```url
9999
http://127.0.0.1:5000
100100
```
@@ -104,7 +104,7 @@ With this we can able to:**
104104
- /health → Health check
105105
- /students → Manage students
106106

107-
- **Run all unit tests:**
107+
**4. Run all unit tests:**
108108
```txt
109109
make test
110110
```
@@ -123,9 +123,10 @@ With this we can able to:**
123123

124124
- Overall I managed to reduce the original `1.26GB` image to just `110MB`, achieving a `91.27%` size decrease while maintaining the same functionality and improving rebuild times by an average of 20 seconds.
125125

126-
#### Docker Commands
126+
### Docker Commands
127+
128+
**1. Build the Docker Image:**
127129

128-
- **Build the Docker Image:**
129130
- Built the image with semantic versioning tags:
130131
```sh
131132
make docker-build DOCKER_IMAGE_TAG=1.0.1
@@ -137,7 +138,7 @@ With this we can able to:**
137138
```
138139
- We can change the `DOCKER_IMAGE_TAG` to any version.
139140

140-
- **Run the Docker Container:**
141+
**2. Run the Docker Container:**
141142
- Run the container
142143
```sh
143144
make docker-run DOCKER_IMAGE_TAG=1.0.1
@@ -152,7 +153,7 @@ With this we can able to:**
152153
http://localhost:5000
153154
```
154155

155-
- **To Remove the Containers:**
156+
**3. To Remove the Containers:**
156157
- To remove the containers using make command
157158
```sh
158159
make docker-stop
@@ -165,7 +166,7 @@ With this we can able to:**
165166
docker rm ${DOCKER_CONTAINER}
166167
```
167168

168-
- **To Remove the unused images:**
169+
**4. To Remove the unused images:**
169170
- To remove the images using make command
170171
```sh
171172
make docker-clean
@@ -177,7 +178,7 @@ With this we can able to:**
177178
docker rmi ${DOCKER_IMAGE}:${DOCKER_IMAGE_TAG}
178179
```
179180

180-
- **For Troubleshooting Container issue:**
181+
**5. For Troubleshooting Container issue:**
181182
- To check container logs using make command
182183
```sh
183184
make docker logs
@@ -190,11 +191,11 @@ With this we can able to:**
190191

191192
## One click local development setup
192193

193-
- Created docker-compose.yml file to containerise Flask (API) and Postgres (DB) together, with persistent volumes for one click local development setup.
194+
**Created docker-compose.yml file to containerise Flask (API) and Postgres (DB) together, with persistent volumes for one click local development setup.**
194195

195196
### Docker Compose Commands
196197

197-
1. To start the service stack
198+
**1. To start the service stack**
198199
```sh
199200
docker compose up -d --build
200201
```
@@ -204,7 +205,7 @@ With this we can able to:**
204205
make up
205206
```
206207

207-
2. To stop and remove everything (including volumes)
208+
**2. To stop and remove everything (including volumes)**
208209
```sh
209210
docker compose down -v
210211
```
@@ -216,9 +217,9 @@ With this we can able to:**
216217
```
217218

218219
### For Database Migration & Seeding
219-
- After starting the containers, you need to run migrations (to create tables) and optionally seed data.
220+
**After starting the containers, you need to run migrations (to create tables) and optionally seed data.**
220221

221-
1. Apply migrations inside the Flask container
222+
**1. Apply migrations inside the Flask container**
222223
```sh
223224
docker exec -it flask-container flask db upgrade
224225
```
@@ -229,7 +230,7 @@ With this we can able to:**
229230
make migrate
230231
```
231232

232-
2. To Seed the database with initial data
233+
**2. To Seed the database with initial data**
233234
```sh
234235
docker exec -it flask-container python seed.py
235236
```
@@ -240,7 +241,7 @@ With this we can able to:**
240241
make seed
241242
```
242243

243-
3. Verify Database
244+
**3. Verify Database**
244245

245246
- To connect into the Postgres container
246247
```sh
@@ -253,7 +254,7 @@ With this we can able to:**
253254
SELECT * FROM students LIMIT 5;
254255
```
255256

256-
4. To Run API container (depends on DB + migrations + seed)
257+
**4. To Run API container (depends on DB + migrations + seed)**
257258

258259
```txt
259260
make run
@@ -266,3 +267,96 @@ With this we can able to:**
266267
http://localhost:5000/students
267268

268269
http://localhost:5000/health
270+
271+
272+
## Setup CI pipeline
273+
274+
**Automation for build, test, and publish of Docker images using GitHub Actions workflow for CI pipeline**
275+
276+
### pipeline stages
277+
- Build API → make sure it compiles.
278+
- Run tests → unit tests should pass.
279+
- Lint → run flake8/pylint/eslint.
280+
- Docker login → authenticate to registry (DockerHub/GHCR).
281+
- Docker build & push → push tagged image.
282+
283+
### Triggering
284+
285+
- Automatically when changes are made inside /api/**.
286+
- Manual trigger (workflow_dispatch).
287+
288+
### Self-hosted runner
289+
- GitHub Actions running on our laptop/VM to simulate real-world self-hosted CI.
290+
291+
**At the end: "Every commit to main will test your code and publish a Docker image"**
292+
293+
## Deploy on Bare Metal
294+
**To deploy on a “production-like” environment without Kubernetes — just Docker + Nginx on a Vagrant box.**
295+
296+
#### Key Points
297+
298+
- Vagrantfile creates a VM (e.g., Ubuntu).
299+
- A provisioning script installs Docker, Docker Compose, Nginx.
300+
- docker-compose.yml deploys:
301+
- 2 API containers (scale with replicas).
302+
- 1 Postgres DB container.
303+
- 1 Nginx container (load balances API replicas).
304+
305+
### Nginx config
306+
307+
```nginx
308+
upstream api_backend {
309+
server api1:5000;
310+
server api2:5000;
311+
}
312+
server {
313+
listen 8080;
314+
location / {
315+
proxy_pass http://api_backend;
316+
}
317+
}
318+
```
319+
- **Access API at http://localhost:8080/api/v1/students.**
320+
- **At the end: "we’ll have a mini production setup with scaling + load balancing".**
321+
322+
## Setup Kubernetes Cluster
323+
324+
**Spin up a 3-node Kubernetes cluster with Minikube.**
325+
326+
#### Key Points
327+
328+
- **Start minikube with 3 nodes:**
329+
```sh
330+
minikube start --nodes=3
331+
```
332+
333+
- **Label nodes:**
334+
- Node A → type=application
335+
- Node B → type=database
336+
- Node C → type=dependent_services
337+
338+
- This enforces workload isolation (apps on one node, DB on another, monitoring tools on another).
339+
340+
**At the end: "we have a real K8s cluster with node roles".**
341+
342+
## Deploy API, DB and other services in Kubernetes
343+
344+
**Move from Docker Compose → Kubernetes deployment.**
345+
346+
#### Key Points
347+
348+
- **Manifests should be modular:**
349+
- **application.yml** → namespace, configmap, secret, deployment, service for API.
350+
- **database.yml** → namespace, deployment, service for Postgres.
351+
352+
- **Init container** → runs DB migrations before starting API.
353+
- **ConfigMaps** → non-sensitive configs (e.g., DB host).
354+
- **Secrets** → sensitive info (DB password).
355+
- **External Secrets Operator + Vault** → manage secrets properly.
356+
- **Services**
357+
- ClusterIP for DB (internal only).
358+
- NodePort/LoadBalancer for API (external access).
359+
- **Namespace isolation** → student-api for app + db, others for observability.
360+
- **Test via Postman**: all endpoints should work and return 200.
361+
362+
**At the end: "Our app is cloud-ready, secure, and scalable on Kubernetes".**

0 commit comments

Comments
 (0)