commit 2443ce80f7208eccc7172796a8b102d4f89a8183 Author: Nitheesh Date: Wed Apr 1 10:00:23 2026 +0200 initial commit diff --git a/z1/NitheeshWork_Documentation.docx b/z1/NitheeshWork_Documentation.docx new file mode 100644 index 0000000..65efa1b Binary files /dev/null and b/z1/NitheeshWork_Documentation.docx differ diff --git a/z1/README.md b/z1/README.md new file mode 100644 index 0000000..baf32a5 --- /dev/null +++ b/z1/README.md @@ -0,0 +1,241 @@ +# NitheeshWork — Multi-Container Task Manager + +A web-based task management application deployed with Docker Compose across **5 isolated containers**, featuring persistent storage, a REST API with Redis caching, and a database management UI. + +--- + +## What the Application Does + +NitheeshWork is a kanban-style task manager where you can: + +- Create, edit, and delete tasks +- Assign each task a **status** (To Do / In Progress / Done) and **priority** (Low / Medium / High) +- View live statistics showing task counts per status +- Filter tasks by priority +- Browse and manage the database directly via pgAdmin +- Call the REST API directly from any HTTP client + +The backend caches the statistics endpoint in Redis (10-second TTL) to reduce database load. The frontend shows a ⚡ indicator when a response is served from cache. + +--- + +## Required Software + +| Software | Minimum Version | Purpose | +|---|---|---| +| Docker Engine | 24.0+ | Container runtime | +| Docker Compose plugin | v2.0+ | Multi-container orchestration | +| Linux (Ubuntu/Debian recommended) | — | Host operating system | + +### Install Docker on Ubuntu/Debian + +```bash +sudo apt update +sudo apt install -y ca-certificates curl gnupg +sudo install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \ + https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \ + | sudo tee /etc/apt/sources.list.d/docker.list +sudo apt update +sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +sudo systemctl start docker && sudo systemctl enable docker +sudo usermod -aG docker $USER && newgrp docker +``` + +--- + +## Containers + +| Container | Image | Port | Role | +|---|---|---|---| +| `nitheeshwork-postgres` | postgres:16-alpine | 5432 (internal) | PostgreSQL relational database — stores all tasks | +| `nitheeshwork-redis` | redis:7-alpine | 6379 (internal) | Redis in-memory cache — caches API stats responses | +| `nitheeshwork-backend` | built locally | 4000 | Node.js/Express REST API — business logic layer | +| `nitheeshwork-frontend` | nginx:1.25-alpine | 8080 | Serves the HTML/JS frontend and proxies /api/ to backend | +| `nitheeshwork-pgadmin` | dpage/pgadmin4 | 5050 | Web UI for browsing and querying PostgreSQL | + +### Container Configuration Details + +**postgres** — configured via environment variables (`POSTGRES_DB`, `POSTGRES_USER`, `POSTGRES_PASSWORD`). Has a healthcheck using `pg_isready` so dependent containers wait until the DB is truly ready before starting. + +**redis** — started with `--appendonly yes` so data is persisted to disk (AOF mode) rather than lost on restart. + +**backend** — custom Node.js image built from `./backend/Dockerfile`. Receives database and cache connection details via environment variables. Automatically seeds 6 sample tasks on first startup if the table is empty. Configured with `restart: unless-stopped`. + +**frontend** — vanilla nginx serving `./frontend/index.html` as a static file. A custom `nginx/default.conf` adds a reverse proxy rule: any request to `/api/` is forwarded to the backend container on port 4000. This allows the browser to talk to one origin (port 8080) for both UI and API. + +**pgadmin** — configured in desktop mode (`SERVER_MODE=False`) so no extra login infrastructure is needed. Email and password set via environment variables. + +--- + +## Virtual Networks + +| Network | Driver | Purpose | +|---|---|---| +| `nitheeshwork-net` | bridge | Private internal network connecting all 5 containers. Containers address each other by service name (e.g. `postgres`, `redis`). No external access except through published ports. | + +All inter-container communication happens over this network. The backend connects to `postgres:5432` and `redis:6379` using Docker's internal DNS — these hostnames are not reachable from outside the network. + +--- + +## Named Volumes + +| Volume | Mounted In | What It Stores | +|---|---|---| +| `nitheeshwork-postgres-data` | `/var/lib/postgresql/data` | All PostgreSQL data files — tasks table and schema | +| `nitheeshwork-redis-data` | `/data` | Redis AOF persistence file — survives restarts | +| `nitheeshwork-pgadmin-data` | `/var/lib/pgadmin` | pgAdmin saved server connections and session data | + +Stopping the application with `stop-app.sh` does **not** remove these volumes. Data persists across restarts and even configuration changes. Only `remove-app.sh` deletes them. + +--- + +## Instructions + +### Prepare (first time only) + +```bash +chmod +x prepare-app.sh start-app.sh stop-app.sh remove-app.sh +./prepare-app.sh +``` + +This builds the backend Docker image, creates the `nitheeshwork-net` network, and provisions all three named volumes. + +### Start + +```bash +./start-app.sh +``` + +Starts all 5 containers. All containers are configured with `restart: unless-stopped` — they will automatically restart if they crash, and will start again after a system reboot (as long as the Docker daemon is running). + +### Pause (stop without losing data) + +```bash +./stop-app.sh +``` + +Stops all containers. Named volumes and data are fully preserved. Resume any time with `./start-app.sh`. + +### Remove everything + +```bash +./remove-app.sh +``` + +Asks for confirmation, then removes all containers, volumes, the network, and the built image. This is irreversible — all task data will be deleted. + +--- + +## Viewing the Application in a Browser + +| URL | What you see | +|---|---| +| http://localhost:8080 | Main NitheeshWork task manager UI | +| http://localhost:4000/api/tasks | Raw JSON API — list of all tasks | +| http://localhost:4000/health | Service health check (JSON) | +| http://localhost:5050 | pgAdmin database management UI | + +### Connecting pgAdmin to PostgreSQL + +1. Open http://localhost:5050 +2. Login: `admin@nitheeshwork.com` / `adminpass` +3. Click **Add New Server** +4. **General tab** → Name: `nitheeshwork` +5. **Connection tab**: + - Host: `postgres` + - Port: `5432` + - Database: `taskdb` + - Username: `taskuser` + - Password: `taskpass` +6. Click **Save** +7. Browse to: `Servers → nitheeshwork → Databases → taskdb → Schemas → public → Tables → tasks` + +--- + +## REST API Reference + +Base URL: `http://localhost:4000/api` + +| Method | Endpoint | Description | +|---|---|---| +| GET | `/tasks` | List all tasks | +| GET | `/tasks?priority=high` | Filter by priority (low/medium/high) | +| GET | `/tasks?status=todo` | Filter by status (todo/in-progress/done) | +| GET | `/tasks/:id` | Get a single task | +| POST | `/tasks` | Create a new task | +| PUT | `/tasks/:id` | Update a task | +| DELETE | `/tasks/:id` | Delete a task | +| GET | `/stats` | Task counts by status (Redis cached) | +| GET | `/health` | Returns postgres + redis health status | + +Example — create a task: +```bash +curl -X POST http://localhost:4000/api/tasks \ + -H "Content-Type: application/json" \ + -d '{"title":"My task","description":"Details here","status":"todo","priority":"high"}' +``` + +--- + +## File Structure + +``` +nitheeshwork/ +├── backend/ +│ ├── Dockerfile ← Node.js image definition +│ ├── package.json ← Dependencies (express, pg, redis, cors) +│ └── server.js ← Express REST API with all endpoints +├── frontend/ +│ └── index.html ← Single-page task manager UI (HTML/CSS/JS) +├── nginx/ +│ └── default.conf ← Nginx config: static files + /api/ proxy +├── docker-compose.yaml ← All 5 service definitions +├── prepare-app.sh ← Build image, create network and volumes +├── start-app.sh ← Start all containers +├── stop-app.sh ← Stop containers, preserve data +├── remove-app.sh ← Full teardown including volumes +└── README.md ← This file +``` + +--- + +## Resources Used + +| Resource | URL | +|---|---| +| Docker Engine documentation | https://docs.docker.com/engine/ | +| Docker Compose documentation | https://docs.docker.com/compose/ | +| PostgreSQL 16 Docker image | https://hub.docker.com/_/postgres | +| Redis 7 Docker image | https://hub.docker.com/_/redis | +| Nginx Docker image | https://hub.docker.com/_/nginx | +| pgAdmin 4 Docker image | https://hub.docker.com/r/dpage/pgadmin4 | +| Node.js 20 Alpine image | https://hub.docker.com/_/node | +| Express.js documentation | https://expressjs.com/ | +| node-postgres (pg) library | https://node-postgres.com/ | +| node-redis library | https://github.com/redis/node-redis | + +--- + +## Use of Artificial Intelligence + +This project was designed and implemented with the assistance of **Claude** (claude.ai), an AI assistant made by Anthropic. + +### AI Agent Used + +| Agent | Model | Role | +|---|---|---| +| Claude (claude.ai) | Claude Sonnet 4.6 | Full application design and code generation | + +### How AI Was Used + +- **Application architecture** — Claude designed the 5-service Docker Compose architecture, selecting appropriate images and deciding how services should communicate. +- **Backend code** — The entire `server.js` Express API (endpoints, PostgreSQL queries, Redis caching logic, health checks, seed data) was written by Claude. +- **Frontend code** — The complete `index.html` single-page application (UI layout, CSS styling, JavaScript fetch calls, live health indicators) was generated by Claude. +- **Docker configuration** — All Dockerfiles, `docker-compose.yaml`, and nginx configuration were created by Claude. +- **Shell scripts** — All four bash scripts (`prepare-app.sh`, `start-app.sh`, `stop-app.sh`, `remove-app.sh`) were written by Claude. +- **Debugging** — Claude diagnosed and fixed issues encountered during deployment (network label conflict, pgAdmin email validation error). +- **Documentation** — This README was written by Claude based on the actual implementation. + +All code was verified by running it on an Ubuntu Linux system inside a VMware virtual machine. diff --git a/z1/docker-compose.yaml b/z1/docker-compose.yaml new file mode 100644 index 0000000..deed071 --- /dev/null +++ b/z1/docker-compose.yaml @@ -0,0 +1,106 @@ +services: + + # ── 1. PostgreSQL Database ────────────────────────────────────────────────── + postgres: + image: postgres:16-alpine + container_name: nitheeshwork-postgres + restart: unless-stopped + environment: + POSTGRES_DB: taskdb + POSTGRES_USER: taskuser + POSTGRES_PASSWORD: taskpass + volumes: + - postgres_data:/var/lib/postgresql/data + networks: + - nitheeshwork-net + healthcheck: + test: ["CMD-SHELL", "pg_isready -U taskuser -d taskdb"] + interval: 10s + timeout: 5s + retries: 5 + + # ── 2. Redis Cache ────────────────────────────────────────────────────────── + redis: + image: redis:7-alpine + container_name: nitheeshwork-redis + restart: unless-stopped + command: redis-server --appendonly yes + volumes: + - redis_data:/data + networks: + - nitheeshwork-net + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 5s + retries: 5 + + # ── 3. Node.js/Express Backend API ───────────────────────────────────────── + backend: + build: + context: ./backend + dockerfile: Dockerfile + container_name: nitheeshwork-backend + restart: unless-stopped + environment: + POSTGRES_HOST: postgres + POSTGRES_DB: taskdb + POSTGRES_USER: taskuser + POSTGRES_PASSWORD: taskpass + REDIS_HOST: redis + PORT: 4000 + ports: + - "4000:4000" + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + networks: + - nitheeshwork-net + + # ── 4. Nginx – Frontend + Reverse Proxy ──────────────────────────────────── + frontend: + image: nginx:1.25-alpine + container_name: nitheeshwork-frontend + restart: unless-stopped + ports: + - "8080:80" + volumes: + - ./frontend:/usr/share/nginx/html:ro + - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro + depends_on: + - backend + networks: + - nitheeshwork-net + + # ── 5. pgAdmin – Database Web UI ─────────────────────────────────────────── + pgadmin: + image: dpage/pgadmin4:latest + container_name: nitheeshwork-pgadmin + restart: unless-stopped + environment: + PGADMIN_DEFAULT_EMAIL: admin@nitheeshwork.com + PGADMIN_DEFAULT_PASSWORD: adminpass + PGADMIN_CONFIG_SERVER_MODE: "False" + PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED: "False" + volumes: + - pgadmin_data:/var/lib/pgadmin + ports: + - "5050:80" + depends_on: + - postgres + networks: + - nitheeshwork-net + +volumes: + postgres_data: + name: nitheeshwork-postgres-data + redis_data: + name: nitheeshwork-redis-data + pgadmin_data: + name: nitheeshwork-pgadmin-data + +networks: + nitheeshwork-net: + driver: bridge diff --git a/z1/nitheeshwork.tar.gz b/z1/nitheeshwork.tar.gz new file mode 100644 index 0000000..d5bd861 Binary files /dev/null and b/z1/nitheeshwork.tar.gz differ diff --git a/z1/prepare-app.sh b/z1/prepare-app.sh new file mode 100644 index 0000000..e54e40f --- /dev/null +++ b/z1/prepare-app.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +# ============================================================ +# prepare-app.sh – Build images, create network & volumes +# ============================================================ +set -euo pipefail + +echo "╔══════════════════════════════════════════════╗" +echo "║ NitheeshWork – Prepare Application ║" +echo "╚══════════════════════════════════════════════╝" + +cd "$(dirname "$0")" + +# ── 1. Docker network ──────────────────────────────────────── +echo "" +echo "▸ Creating Docker network: nitheeshwork-net" +docker network inspect nitheeshwork-net >/dev/null 2>&1 \ + && echo " Network already exists, skipping." \ + || docker network create nitheeshwork-net + +# ── 2. Named volumes ───────────────────────────────────────── +echo "" +echo "▸ Creating named volumes…" +for vol in nitheeshwork-postgres-data nitheeshwork-redis-data nitheeshwork-pgadmin-data; do + docker volume inspect "$vol" >/dev/null 2>&1 \ + && echo " Volume $vol already exists, skipping." \ + || docker volume create "$vol" && echo " Created: $vol" +done + +# ── 3. Build backend image ─────────────────────────────────── +echo "" +echo "▸ Building backend Docker image…" +docker build -t nitheeshwork-backend:latest ./backend + +echo "" +echo "✔ Preparation complete." +echo " Run ./start-app.sh to start all services." diff --git a/z1/remove-app.sh b/z1/remove-app.sh new file mode 100644 index 0000000..8c8a93c --- /dev/null +++ b/z1/remove-app.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +# ============================================================ +# remove-app.sh – Remove ALL NitheeshWork containers, images, +# volumes, and network (full cleanup) +# ============================================================ +set -euo pipefail + +echo "╔══════════════════════════════════════════════╗" +echo "║ NitheeshWork – Remove Application ║" +echo "╚══════════════════════════════════════════════╝" +echo "" +echo "⚠ WARNING: This will delete all data, including" +echo " the PostgreSQL database and Redis cache." +echo "" +read -rp " Are you sure? Type 'yes' to confirm: " confirm +[[ "$confirm" == "yes" ]] || { echo "Aborted."; exit 0; } + +cd "$(dirname "$0")" + +echo "" +echo "▸ Stopping and removing containers…" +docker compose down --remove-orphans 2>/dev/null || true + +echo "" +echo "▸ Removing named volumes…" +for vol in nitheeshwork-postgres-data nitheeshwork-redis-data nitheeshwork-pgadmin-data; do + docker volume rm "$vol" 2>/dev/null && echo " Removed: $vol" || echo " Volume $vol not found, skipping." +done + +echo "" +echo "▸ Removing Docker network…" +docker network rm nitheeshwork-net 2>/dev/null && echo " Removed: nitheeshwork-net" || echo " Network not found, skipping." + +echo "" +echo "▸ Removing built images…" +docker rmi nitheeshwork-backend:latest 2>/dev/null && echo " Removed: nitheeshwork-backend:latest" || echo " Image not found, skipping." + +echo "" +echo "✔ All NitheeshWork resources have been removed." diff --git a/z1/start-app.sh b/z1/start-app.sh new file mode 100644 index 0000000..c173c2d --- /dev/null +++ b/z1/start-app.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +# ============================================================ +# start-app.sh – Start all NitheeshWork services +# ============================================================ +set -euo pipefail + +echo "╔══════════════════════════════════════════════╗" +echo "║ NitheeshWork – Start Application ║" +echo "╚══════════════════════════════════════════════╝" + +cd "$(dirname "$0")" + +echo "" +echo "▸ Starting services with docker compose…" +docker compose up -d --remove-orphans + +echo "" +echo "▸ Waiting for services to become healthy…" +sleep 6 + +docker compose ps + +echo "" +echo "╔══════════════════════════════════════════════════════╗" +echo "║ NitheeshWork is ready! ║" +echo "╠══════════════════════════════════════════════════════╣" +echo "║ 🌐 Web App (frontend) → http://localhost:8080 ║" +echo "║ 🔌 REST API (backend) → http://localhost:4000 ║" +echo "║ 🗄️ pgAdmin (DB UI) → http://localhost:5050 ║" +echo "║ ║" +echo "║ pgAdmin login: admin@nitheeshwork.com / adminpass ║" +echo "║ PostgreSQL: host=postgres db=taskdb ║" +echo "║ user=taskuser pass=taskpass ║" +echo "╚══════════════════════════════════════════════════════╝" diff --git a/z1/stop-app.sh b/z1/stop-app.sh new file mode 100644 index 0000000..28255ef --- /dev/null +++ b/z1/stop-app.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +# ============================================================ +# stop-app.sh – Stop all NitheeshWork services (data preserved) +# ============================================================ +set -euo pipefail + +echo "╔══════════════════════════════════════════════╗" +echo "║ NitheeshWork – Stop Application ║" +echo "╚══════════════════════════════════════════════╝" + +cd "$(dirname "$0")" + +echo "" +echo "▸ Stopping all services (volumes and data are preserved)…" +docker compose stop + +echo "" +echo "✔ All services stopped." +echo " Data in volumes is preserved." +echo " Run ./start-app.sh to resume."