How sarowar-alam/3-tier-with-docker works
1. This repository is a training-oriented wrapper around one real application: a 3-tier BMI Health Tracker. The app itself lives at the repo root, while the 01-fundamentals-containerizing and 02-compose-migration folders contain progressively more advanced Docker packaging, orchestration, and observability material for the same stack.
2. The runtime architecture is a classic three-tier flow: browser/client UI → REST API → PostgreSQL. In production, the frontend is served from an Nginx container on port 80, the backend runs as a Node.js/Express service on port 3000, and the database is PostgreSQL on port 5432.
3. The frontend is a React application built with Vite. App.jsx wires the page together, MeasurementForm.jsx handles user input, TrendChart.jsx renders historical trends, and api.js is the boundary where the UI talks to the backend. In production the frontend is compiled to static assets and served by Nginx; in development it uses Vite hot reload.
4. The backend is the application and business-logic boundary. server.js boots the service, routes.js defines the HTTP API surface, calculations.js contains BMI/BMR/daily-calorie logic, and db.js encapsulates persistence access. The backend also includes container-friendly startup behavior so it can tolerate the database not being ready immediately.
5. Persistence is centered on a measurements history model. The migrations under backend/migrations create the measurements table and later add a measurement date field, which supports the app’s historical tracking and 30-day trend views. The database setup script under database/ supports local bootstrapping outside the container path.
6. 01-fundamentals-containerizing is the “single-container-image” layer of the course. It contains production and development Dockerfiles for both backend and frontend, .dockerignore files, an Nginx config for serving the frontend, and build scripts for packaging both images. This folder is about image construction, layering, and runtime split between dev and prod.
7. 02-compose-migration is the orchestration layer. It defines a production Compose stack, a development Compose stack, and a separate monitoring stack. This is where service discovery, network wiring, volume-backed persistence, environment-variable injection, and startup dependencies/health checks become part of the architecture.
8. The observability subsystem is isolated from the application stack but connected to it. Prometheus collects metrics, Loki stores logs, Promtail ships logs from containers, and Grafana provides dashboards and datasource provisioning. The included BMI dashboard JSON indicates the monitoring layer is intended to visualize this specific app, not just generic container health.
9. CI/CD is represented by .github/workflows/docker-build-push.yml. Its role is to build and publish container images, making the Docker artifacts first-class deployable units rather than just local classroom examples. The README calls out DockerHub and AWS ECR as likely registry targets.
10. The repository also includes a small runtime/process-management boundary in backend/ecosystem.config.js, which suggests a production process manager configuration for the Node service. That sits between the application code and the container runtime, helping define how the backend is launched and supervised.
11. The setup, cleanup, and scripts folders in both class directories are operational scaffolding. They don’t change the application architecture, but they do encode how the stack is started, stopped, reset, and demonstrated across Windows PowerShell and Unix shells.
12. Net result: the core application is a stateful web system with a clear split between presentation, API/business logic, and relational persistence, while the surrounding repository layers add container image buildability, multi-container orchestration, observability, and delivery automation.
Main entry points: src Backend · 02-compose-migration Compose stacks · App.jsx App shell · monitoring Monitoring
Components 19
Core App
Browser UI, API, and PostgreSQL data layer
- Frontend · Client-facing app served statically in production and via Vite in development
frontend - App shell · Wires the main page and UI flow together
frontend/src/App.jsx - Input form · Collects BMI measurement data from the user
frontend/src/components/MeasurementForm.jsx - Trend chart · Renders historical measurements and trend views
frontend/src/components/TrendChart.jsx - API client · Frontend boundary for talking to the backend service
frontend/src/api.js - Backend · Business-logic and HTTP boundary for the application
backend/src - Server boot · Starts the API service and handles runtime startup concerns
backend/src/server.js - Routes · Defines the REST API surface
backend/src/routes.js - Calculations · BMI, BMR, and calorie-related computations
backend/src/calculations.js - DB access · Encapsulates database reads and writes from the backend
backend/src/db.js - Migrations · Creates and evolves the measurements table and date field
backend/migrations - PostgreSQL · Stores measurement history for historical and trend views
database - Process manager · Defines supervised backend launch behavior for production
backend/ecosystem.config.js
Containerization
Image build and runtime packaging for the app
- Docker images · Builds production and development images for frontend and backend
01-fundamentals-containerizing - Nginx serve · Serves compiled frontend assets in production
01-fundamentals-containerizing/frontend/nginx.conf
Compose Orchestration
Multi-container dev/prod stacks and operational scripts
- Compose stacks · Defines dev, prod, and monitoring orchestration layouts
02-compose-migration
Observability
Metrics, logs, and dashboards for the stack
- Monitoring · Prometheus, Loki, Promtail, and Grafana for the app
02-compose-migration/monitoring - BMI dashboard · Grafana dashboard tailored to this application
02-compose-migration/monitoring/grafana/dashboards/bmi-app-dashboard.json
Delivery
CI workflow for building and publishing images
- Build pipeline · Builds and publishes container images
.github/workflows/docker-build-push.yml
Connections 23
- Frontend → App shell: contains · React app composition lives here
- App shell → Input form: uses · Page includes measurement input form
- App shell → Trend chart: uses · Page includes trend visualization
- App shell → API client: calls · UI sends data and fetches history through API boundary
- API client → Routes: requests · HTTP client talks to backend endpoints
- Backend → Server boot: boots · Service entrypoint starts the application
- Server boot → Routes: mounts · Server exposes the HTTP routes
- Routes → Calculations: uses · Routes apply BMI domain logic
- Routes → DB access: persists · Routes store and retrieve measurement data
- DB access → PostgreSQL: reads/writes · Database adapter talks to PostgreSQL
- Migrations → PostgreSQL: migrates · Schema changes are applied to the database
- Frontend → Nginx serve: served by · Production frontend is delivered by Nginx
- Docker images → Frontend: packages · Builds frontend image variants
- Docker images → Backend: packages · Builds backend image variants
- Compose stacks → Backend: runs · Compose starts backend service container
- Compose stacks → Frontend: runs · Compose starts frontend service container
- Compose stacks → PostgreSQL: runs · Compose wires database service and persistence
- Compose stacks → Monitoring: includes · Monitoring stack is deployed alongside application stacks
- Monitoring → BMI dashboard: provisions · Grafana is seeded with an app-specific dashboard
- Monitoring → Backend: observes · Metrics and logs are collected from the app services
- Monitoring → PostgreSQL: observes · Infrastructure monitoring includes the data layer
- Build pipeline → Docker images: builds · CI produces deployable container artifacts
- Process manager → Backend: supervises · Production launch configuration for the Node service