This repository demonstrates practical, production-minded Docker and Kubernetes patterns for a simple Node.js API. It's designed to show you that you can build and deploy containers the "right way" with separate development and production images, a local compose workflow, and Kubernetes manifests that include rolling updates, probes, resource limits, and ConfigMap usage.
Why this project
- Clear dev / prod split:
app/Dockerfile.devfor iterative local development (nodemon + volume mounts) andapp/Dockerfile.prodfor a lean production image (npm ci --only=production). - Compose-based local dev:
compose.yamlshows how to run the app with a bind mount for fast feedback loops. - Kubernetes-ready: manifests in
k8s/show best practices like RollingUpdate strategy, liveness/readiness probes, resource requests/limits, and ConfigMap usage. - Health endpoint:
/healthis implemented to power probes and quick sanity checks.
Repo layout
docker-mastery
├─ 📁app
│ ├─ 📁node_modules
│ ├─ 📄Dockerfile.dev
│ ├─ 📄Dockerfile.prod
│ ├─ 📄package.json
│ └─ 📄server.js
├─ 📁k8s
│ ├─ 📄configmap.yaml
│ ├─ 📄deployment.yaml
│ └─ 📄service.yaml
├─ 📄.gitignore
├─ 📄README.md
└─ 📄compose.yaml
Key Kubernetes concepts demonstrated
-
manifests in
k8s/show best practices like RollingUpdate strategy, liveness/readiness probes, resource requests/limits, and ConfigMap usage. -
replicas: 2andRollingUpdatewithmaxSurge: 1andmaxUnavailable: 0for zero-downtime updates -
imagePullPolicy: Never(set for local-cluster development; change toIfNotPresentorAlwaysfor remote registries) -
resource
requests/limitsfor safer scheduling -
livenessProbeandreadinessProbeagainst/health -
k8s/service.yamlexposes the app as aNodePort(suitable for local clusters). Change toLoadBalanceror add an Ingress for cloud deployments. -
Kubernetes manifests include probes, resource constraints, and rolling update strategy — minimal yet production-relevant.
-
ConfigMap usage demonstrates how to pass non-sensitive config (
k8s/configmap.yaml). Use Secrets for credentials.
Architecture (ASCII diagram)
Local development (Docker Compose):
Developer laptop
└─ docker compose (compose.yaml)
└─ Container (Dockerfile.dev)
└─ Node.js app (nodemon, bind-mounted source)
Kubernetes deployment (k8s/):
+----------------+
| Image registry | <- (build/push) or local cluster image load
+--------+-------+
|
+-------------v--------------+
| Kubernetes cluster (kind) |
| +------------------------+ |
| | Deployment (replicas=2) | |
| | - Pod (container: api) | |
| +-----------+------------+ |
| | |
| Service (NodePort) |
+-------------+--------------+
|
External
traffic / tests
Auxiliary: ConfigMap provides `APP_NAME`, `/health` used by liveness/readiness probes.
What this project does NOT try to solve
This repo is intentionally minimal and focused on demonstrating core container and Kubernetes patterns. It does NOT attempt to be a full production platform. Notable omissions:
- CI/CD pipeline: no automated build/test/push pipeline is included (you can add GitHub Actions or similar).
- Secrets management: sensitive values are not stored in
Secretsor a vault; only a ConfigMap is shown. - Persistent storage: there is no PersistentVolume / database or migration strategy included.
- Ingress + TLS: the example uses a
NodePortservice; no Ingress controller or TLS termination is configured. - Image registry best-practices: pushing, tagging, signing, and immutable tags for registries are left to the integrator.
- Full security hardening: the Dockerfiles are basic examples; further hardening (non-root user, minimized layers, image scanning) is recommended.
- Observability: logging aggregation, metrics, tracing, and alerting are out of scope.
- Autoscaling & advanced K8s operators: HPA, custom controllers, and operator patterns are not covered.
- Multi-region, high-availability, and cloud-provider networking specifics are not included.
Quick start — local development (Docker Compose)
- From the repository root, start the dev environment:
docker compose -f compose.yaml up --build- Open http://localhost:3000 — the container runs with
Dockerfile.devand the host folder is mounted into the container for instant code changes.
Build and run the production image (locally)
# build the prod image
docker build -f app/Dockerfile.prod -t docker-mastery:1.0 ./app
# run the prod container
docker run --rm -p 3000:3000 docker-mastery:1.0Deploy to Kubernetes (local cluster)
- Build the image and make it available to your cluster.
- For kind:
docker build -f app/Dockerfile.prod -t docker-mastery:1.0 ./app
kind load docker-image docker-mastery:1.0 --name kind
kubectl apply -f k8s/- For minikube:
minikube image load docker-mastery:1.0
kubectl apply -f k8s/- The
k8s/deployment.yamluses the imagedocker-mastery:1.0andimagePullPolicy: Neverfor local-cluster development. Apply the manifests withkubectl apply -f k8s/after loading the image into your cluster.
Notes & best-practice highlights in this repo
- Lightweight base images:
node:18-alpinekeeps images small and fast. - Separate install steps:
npm install(dev) vsnpm ci --only=production(prod) to ensure reproducible production installs. - Volumes in compose enable live reloading with
nodemonduring development. - Kubernetes manifests include probes, resource constraints, and rolling update strategy — minimal yet production-relevant.
- ConfigMap usage demonstrates how to pass non-sensitive config (
k8s/configmap.yaml). Use Secrets for credentials.
Health & readiness
- GET
/healthreturns 200 OK and is used by Kubernetes probes.
What to add next (suggested improvements)
- Add
Ingressmanifest and an Ingress controller (e.g., NGINX) for real HTTP routing - Add
Secretresources for sensitive configuration - Add CI pipeline (GitHub Actions) to build, scan, and push images to a registry
- Add multi-stage Dockerfile or explicit non-root user for improved security
If you'd like, I can:
- add a sample GitHub Actions workflow to build and push images,
- convert the
k8s/servicetoIngresswith TLS, - or harden the Dockerfile to run as a non-root user.
Enjoy — this repo is a compact showcase of practical Docker + Kubernetes patterns you can point to in interviews or demos.