Skip to content

Commit 998237e

Browse files
authored
Merge pull request #21 from anasahmed07/004-minikube-k8s-deployment
004 minikube k8s deployment
2 parents 737750b + 3a555a5 commit 998237e

51 files changed

Lines changed: 2155 additions & 32 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,6 @@ __pycache__/
2020
.venv/
2121
venv/
2222
*.egg-info/
23+
24+
# Kubernetes / Helm
25+
helm/doit/values.secret.yaml

AGENTS.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,3 +223,12 @@ Each subfolder (`frontend/`, `backend/`, `doit-cli/`) contains its own `AGENTS.m
223223

224224
## Code Standards
225225
See `.specify/memory/constitution.md` for code quality, testing, performance, security, and architecture principles.
226+
227+
## Active Technologies
228+
- Python 3.13+ (MCP service), TypeScript (Frontend) (003-conversational-mcp-chatbot)
229+
- PostgreSQL (Neon Serverless) — shared database, new `conversation` + `message` tables (003-conversational-mcp-chatbot)
230+
- Docker, Minikube, Helm 3, Kubernetes, nginx Ingress (004-minikube-k8s-deployment)
231+
232+
## Recent Changes
233+
- 004-minikube-k8s-deployment: Added Docker multi-stage builds, Helm umbrella chart, Minikube K8s deployment
234+
- 003-conversational-mcp-chatbot: Added Python 3.13+ (MCP service), TypeScript (Frontend)

CLAUDE.md

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1 @@
11
AGENTS.md
2-
3-
## Active Technologies
4-
- Python 3.13+ (MCP service), TypeScript (Frontend) (003-conversational-mcp-chatbot)
5-
- PostgreSQL (Neon Serverless) — shared database, new `conversation` + `message` tables (003-conversational-mcp-chatbot)
6-
7-
## Recent Changes
8-
- 003-conversational-mcp-chatbot: Added Python 3.13+ (MCP service), TypeScript (Frontend)

backend/.dockerignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ __pycache__/
33
*$py.class
44
.venv/
55
.env
6+
.env*
67
.pytest_cache/
78
.ruff_cache/
89
tests/
10+
.git
11+
.gitignore
12+
*.md
13+
.vscode
14+
.idea

backend/Dockerfile

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,36 @@
1-
# Use Python 3.13 slim image
1+
# Stage 1: Builder
2+
FROM python:3.13-slim AS builder
3+
4+
WORKDIR /app
5+
6+
# Install uv
7+
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
8+
9+
# Install dependencies first (layer caching)
10+
COPY pyproject.toml uv.lock ./
11+
RUN uv sync --frozen --no-cache
12+
13+
# Copy source
14+
COPY src/ src/
15+
16+
# Stage 2: Runtime
217
FROM python:3.13-slim
318

4-
# Set working directory
519
WORKDIR /app
620

7-
# Install UV
21+
# Install uv for uv run
822
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
923

10-
# Copy all files
11-
COPY . .
24+
# Copy built artifacts from builder
25+
COPY --from=builder /app/.venv .venv
26+
COPY --from=builder /app/src src
27+
COPY --from=builder /app/pyproject.toml pyproject.toml
1228

13-
# Install dependencies using UV
14-
RUN uv sync --frozen --no-cache
29+
ENV PYTHONUNBUFFERED=1
1530

16-
# Expose the port the app runs on (7860 for Hugging Face)
1731
EXPOSE 8000
1832

19-
# Set environment variables
20-
ENV PYTHONUNBUFFERED=1
33+
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
34+
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1
2135

22-
# Run the application using UV
2336
CMD ["uv", "run", "prod"]

docs/README.md

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,13 @@ DoIt is a productivity application that combines a traditional web interface wit
7272
- Real-time SSE streaming with markdown rendering
7373
- Persistent conversation history with create, switch, and delete support
7474

75+
### Local Kubernetes Deployment
76+
- Multi-stage Docker builds for all services (optimized image sizes)
77+
- Umbrella Helm chart with subcharts for frontend, backend, and MCP
78+
- Minikube deployment with nginx Ingress for path-based routing
79+
- Health probes (liveness/readiness) on all services
80+
- Secrets management via gitignored `values.secret.yaml`
81+
7582
### Auth and Infrastructure
7683
- Better Auth with email/password, Google, and GitHub OAuth
7784
- Docker Compose with three services (backend, mcp, frontend)
@@ -85,6 +92,7 @@ doit/
8592
+-- frontend/ # Next.js 16, TypeScript, Tailwind, shadcn/ui
8693
+-- backend/ # FastAPI, SQLAlchemy, Alembic, Better Auth
8794
+-- mcp/ # FastMCP, Gemini agent, MCP tools (Python 3.13+)
95+
+-- helm/doit/ # Umbrella Helm chart with subcharts
8896
+-- doit-cli/ # Original CLI app
8997
+-- specs/ # Feature specs, plans, and task breakdowns
9098
+-- docs/ # Documentation
@@ -132,23 +140,52 @@ cd mcp && uv sync && uv run dev
132140
cd frontend && npm install && npm run dev
133141
```
134142

143+
### Run with Kubernetes (Minikube)
144+
145+
```bash
146+
# Start Minikube and enable Ingress
147+
minikube start --cpus=4 --memory=8192 --driver=docker
148+
minikube addons enable ingress
149+
150+
# Build images inside Minikube
151+
eval $(minikube docker-env)
152+
docker build -t doit-backend:latest ./backend
153+
docker build -t doit-mcp:latest ./mcp
154+
docker build -t doit-frontend:latest ./frontend
155+
156+
# Configure secrets
157+
cp helm/doit/values.secret.yaml.example helm/doit/values.secret.yaml
158+
# Edit values.secret.yaml with your actual DATABASE_URL, BETTER_AUTH_SECRET, GEMINI_API_KEY
159+
160+
# Deploy
161+
helm dependency update ./helm/doit
162+
helm install doit ./helm/doit -f ./helm/doit/values.secret.yaml
163+
164+
# Add DNS entry (use minikube ip to get the IP)
165+
# Add to /etc/hosts: <minikube-ip> doit.local
166+
167+
# Access at http://doit.local
168+
```
169+
135170
## Tech Stack
136171

137172
| Layer | Technology |
138173
|-------|-----------|
139174
| Frontend | Next.js 16, TypeScript, Tailwind CSS, shadcn/ui |
140175
| Backend API | FastAPI, SQLModel, Alembic, Pydantic |
141-
| MCP Service | FastMCP,Openai agents sdk, Google Gemini, FastAPI (SSE) |
176+
| MCP Service | FastMCP, Openai agents sdk, Google Gemini, FastAPI (SSE) |
142177
| Database | PostgreSQL (Neon Serverless) |
143178
| Auth | Better Auth (email, Google, GitHub OAuth) |
144179
| CLI | Python, Rich, prompt-toolkit |
145180
| DevOps | Docker Compose, GitHub Actions, Hugging Face Spaces |
181+
| Kubernetes | Minikube, Helm 3, nginx Ingress |
146182

147183
## Documentation
148184

149185
- [Phase 1 — CLI](phase%201%20-%20doit-cli/) — Terminal task manager with slash commands and smart autocomplete
150186
- [Phase 2 — Full-Stack Web App](phase%202%20-%20fullstack%20web%20app/phase%202.md) — Next.js + FastAPI web platform with auth, projects, Kanban, and notes
151187
- [Phase 3 — Conversational AI](phase%203%20-%20conversational%20mcp%20chatbot/phase%203.md) — MCP-powered chatbot with Gemini agent and 15 natural-language tools
188+
- [Phase 4 — Local K8s Deployment](phase%204%20-%20local%20k8s%20deployment/phase%204.md) — Minikube deployment with Helm charts and Ingress routing
152189

153190
## Releases
154191

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# Phase 4: Local Kubernetes Deployment
2+
3+
## Overview
4+
5+
Phase 4 packages the DoIt platform for local Kubernetes deployment using Minikube. All three services (frontend, backend, MCP) are containerized with optimized multi-stage Docker builds and orchestrated through an umbrella Helm chart with subcharts.
6+
7+
## Architecture
8+
9+
```
10+
Browser → Ingress (doit.local)
11+
├── / → Frontend Service (ClusterIP :3000)
12+
├── /api → Backend Service (ClusterIP :8000)
13+
└── /mcp → MCP Service (ClusterIP :8080)
14+
15+
Internal (server-side):
16+
Frontend Pod ──BACKEND_URL──→ Backend Service (doit-backend:8000)
17+
Frontend Pod ──MCP_URL──────→ MCP Service (doit-mcp:8080)
18+
19+
External:
20+
All Pods ──DATABASE_URL──→ Neon PostgreSQL (internet)
21+
```
22+
23+
## Components
24+
25+
### Docker Images
26+
27+
| Service | Base Image | Stages | Port | Size |
28+
|---------|-----------|--------|------|------|
29+
| Backend | python:3.13-slim | 2 (builder + runtime) | 8000 | ~200-300MB |
30+
| MCP | python:3.13-slim | 2 (builder + runtime) | 8080 | ~200-300MB |
31+
| Frontend | node:20-alpine | 3 (deps + builder + runtime) | 3000 | ~100-200MB |
32+
33+
### Helm Chart Structure
34+
35+
```
36+
helm/doit/ # Umbrella chart
37+
├── Chart.yaml # Dependencies on subcharts
38+
├── values.yaml # Default configuration
39+
├── values.secret.yaml.example # Secret template
40+
├── .helmignore
41+
├── templates/
42+
│ ├── ingress.yaml # Path-based routing
43+
│ └── _helpers.tpl # Common helpers
44+
└── charts/
45+
├── frontend/ # Frontend subchart
46+
│ └── templates/ # Deployment, Service, ConfigMap, Secret
47+
├── backend/ # Backend subchart
48+
│ └── templates/ # Deployment, Service, ConfigMap, Secret
49+
└── mcp/ # MCP subchart
50+
└── templates/ # Deployment, Service, ConfigMap, Secret
51+
```
52+
53+
### Kubernetes Resources (per deployment)
54+
55+
- 3 Deployments (one per service)
56+
- 3 Services (ClusterIP)
57+
- 3 ConfigMaps (non-sensitive env vars)
58+
- 3 Secrets (credentials, API keys)
59+
- 1 Ingress (shared, path-based routing)
60+
61+
## Health Checks
62+
63+
| Service | Path | Liveness | Readiness |
64+
|---------|------|----------|-----------|
65+
| Backend | `/health` | 30s interval | 10s interval |
66+
| MCP | `/health` | 30s interval | 10s interval |
67+
| Frontend | `/` | 30s interval | 10s interval |
68+
69+
## Configuration
70+
71+
### Environment Variables (ConfigMaps)
72+
73+
| Service | Variable | Value |
74+
|---------|----------|-------|
75+
| Backend | `CORS_ORIGINS` | `http://doit.local` |
76+
| MCP | `MCP_HOST` | `0.0.0.0` |
77+
| MCP | `MCP_PORT` | `8080` |
78+
| Frontend | `BETTER_AUTH_URL` | `http://doit.local` |
79+
| Frontend | `NEXT_PUBLIC_BETTER_AUTH_URL` | `http://doit.local` |
80+
| Frontend | `NEXT_PUBLIC_API_URL` | `http://doit.local/api` |
81+
| Frontend | `BACKEND_URL` | `http://doit-backend:8000` |
82+
| Frontend | `MCP_URL` | `http://doit-mcp:8080` |
83+
84+
### Secrets (values.secret.yaml)
85+
86+
| Key | Required | Used By |
87+
|-----|----------|---------|
88+
| `global.databaseUrl` | Yes | All services |
89+
| `global.betterAuthSecret` | Yes | Backend, Frontend |
90+
| `global.geminiApiKey` | Yes | MCP |
91+
| `global.googleClientId` | No | Frontend |
92+
| `global.googleClientSecret` | No | Frontend |
93+
| `global.githubClientId` | No | Frontend |
94+
| `global.githubClientSecret` | No | Frontend |
95+
96+
## Quickstart
97+
98+
See [quickstart.md](../../specs/004-minikube-k8s-deployment/quickstart.md) for the full deployment guide.
99+
100+
```bash
101+
# 1. Start Minikube
102+
minikube start --cpus=4 --memory=8192 --driver=docker
103+
minikube addons enable ingress
104+
105+
# 2. Build images
106+
eval $(minikube docker-env)
107+
docker build -t doit-backend:latest ./backend
108+
docker build -t doit-mcp:latest ./mcp
109+
docker build -t doit-frontend:latest ./frontend
110+
111+
# 3. Configure secrets
112+
cp helm/doit/values.secret.yaml.example helm/doit/values.secret.yaml
113+
# Edit with real values
114+
115+
# 4. Deploy
116+
helm dependency update ./helm/doit
117+
helm install doit ./helm/doit -f ./helm/doit/values.secret.yaml
118+
119+
# 5. DNS
120+
echo "$(minikube ip) doit.local" | sudo tee -a /etc/hosts
121+
122+
# 6. Access
123+
open http://doit.local
124+
```
125+
126+
## Prerequisites
127+
128+
- Docker Desktop 4.x+
129+
- Minikube (4 CPUs / 8GB RAM minimum)
130+
- Helm 3
131+
- kubectl
132+
- 16GB+ total RAM on host machine
133+
134+
## Technologies
135+
136+
| Technology | Purpose |
137+
|------------|---------|
138+
| Docker | Multi-stage container builds |
139+
| Minikube | Local Kubernetes cluster |
140+
| Helm 3 | Package management and templating |
141+
| nginx Ingress | Path-based HTTP routing |
142+
| Kubernetes | Container orchestration |

frontend/.dockerignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
node_modules
2+
.next
3+
.env*
4+
.git
5+
.gitignore
6+
*.md
7+
.vscode
8+
.idea

frontend/Dockerfile

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Stage 1: Dependencies
2+
FROM node:20-alpine AS deps
3+
4+
WORKDIR /app
5+
6+
COPY package.json package-lock.json ./
7+
RUN npm ci
8+
9+
# Stage 2: Builder
10+
FROM node:20-alpine AS builder
11+
12+
WORKDIR /app
13+
14+
COPY --from=deps /app/node_modules node_modules
15+
COPY . .
16+
17+
ENV NEXT_TELEMETRY_DISABLED=1
18+
19+
RUN npm run build
20+
21+
# Stage 3: Runtime
22+
FROM node:20-alpine
23+
24+
WORKDIR /app
25+
26+
ENV NODE_ENV=production
27+
ENV NEXT_TELEMETRY_DISABLED=1
28+
ENV HOSTNAME=0.0.0.0
29+
ENV PORT=3000
30+
31+
# Copy standalone output
32+
COPY --from=builder /app/.next/standalone ./
33+
COPY --from=builder /app/.next/static .next/static
34+
COPY --from=builder /app/public public
35+
36+
EXPOSE 3000
37+
38+
CMD ["node", "server.js"]

frontend/next.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { NextConfig } from "next";
22

33
const nextConfig: NextConfig = {
4-
/* config options here */
4+
output: "standalone",
55
};
66

77
export default nextConfig;

0 commit comments

Comments
 (0)