← Back to blog
January 10, 2026
DevOps Runbook (Phase A): Dockerize + Postgres + Zero‑Downtime Rolling Updates
Long-form Markdown test article (local file storage).
DevOps Runbook (Phase A): Dockerize + Postgres + Zero‑Downtime Rolling Updates
This doc captures what we did to:
- Dockerize the NestJS API
- Run API + Postgres locally with Docker Compose
- Push the image to GHCR
- Deploy to a Kubernetes homelab cluster with Postgres
- Stabilize health probes and rollouts for zero‑downtime RollingUpdate
- Install NGINX Ingress (homelab) and validate no downtime during rollouts
It also documents the bugs we hit and how we fixed them.
0) Pre-reqs
- Docker (Docker Desktop or docker engine) available on the machine that builds images
kubectlconfigured to talk to your cluster- Optional but recommended:
helm(for Postgres chart) - A working CNI and CoreDNS in the cluster
1) Dockerize the API (multi-stage build)
What we added
Dockerfile: multi-stage build that produces a small runtime image.dockerignore: already existed and was good
Notes / decisions
- We used Debian slim base images instead of Alpine because the app depends on
bcrypt(native addon). Alpine often introduces build/runtime pain for native modules unless you install extra build deps. - The container listens on
PORT(yoursrc/main.tsalready supportsPORT, typically 8080 for platforms like Cloud Run).
Build locally
docker build -t wakari-api:local .
2) Local dev with Docker Compose (API + Postgres as separate containers)
What we changed
- Extended
docker-compose.ymlto include:apiservice built from theDockerfile- existing
postgresservice - wiring via env vars:
WAKARI_DB_HOST=postgres, etc. - Postgres healthcheck +
depends_onso API waits until DB is healthy
Run
docker compose up --build
Smoke test
/healthshould return 200
curl -sS -i http://localhost:8080/health
Summary
| Concept | User | ServiceAccount |
|---|---|---|
| Create identity | openssl → CSR → kubectl certificate approve | kubectl create sa |
| Authenticate | Client certificate (TLS) | Projected JWT token |
| Identify in RBAC | kind: User, name: alice | kind: ServiceAccount, name: deploy-bot, namespace: app |
| Impersonate for testing | --as=alice | --as=system:serviceaccount:app:deploy-bot |
| Group support | O= field in cert → kind: Group | system:serviceaccounts:<ns> (automatic) |
| Best for | Human access, external CI | Pod-to-API access, operators, controllers |