From Blueprint to Cloud
A visual documentation log charting how a simple idea evolved into a deployed containerized application.
Pipeline Milestones
The Genesis: Project Inception
The Deep Dive Into Docker
Instead of relying on basic local node environments, the documentation site was treated as a proper microservice. To keep environments consistent and minimize image size, we implemented a 3-stage multi-stage Docker build. This separated the heavy compilation tools from the final runtime container.
FROM node:20-alpine AS deps → RUN npm ciRather than a standard package update, we used npm ci. This locked in the exact dependency tree from the lockfile, creating a clean, reliable cache layer that sped up subsequent builds.
FROM node:20-alpine AS builder → RUN npm run buildThis environment takes the dependencies, processes the raw source files, and builds the application. It runs the Velite engine to compile markdown into a highly optimized Next.js production bundle.
FROM node:20-alpine AS runner → EXPOSE 3000 → CMD ["node", "server.js"]The final step strips away all source files and development tools. By extracting only the necessary standalone binaries and static assets, we produced a secure, lightweight Alpine-based container.
To keep the Docker daemon running smoothly, we added a strict .dockerignore file. By excluding local artifacts like node_modules/ and .next/, we drastically cut down the build context sent to the engine. This optimization ultimately resulted in a highly efficient output container weighing in at roughly 60MB.
Azure Cloud Provisioning
Production Diagnostics
A summary of the real-world bugs encountered during the deployment phase, highlighting what broke and how we patched it.
Root Cause: Initial Docker builds were copying massive local cache folders directly into the engine, slowing down the pipeline and wasting disk space.
Root Cause: Next.js threw compilation errors during the build stage due to outdated dependency constraints in the default `node:18-alpine` image.
Root Cause: Docker failed to bind to host port 3000 with an `address already in use` error, even though no background processes were actively using it.
Root Cause: External web traffic couldn't reach the NGINX proxy because default firewalls on both Ubuntu (`ufw`) and Azure (NSG) were blocking incoming requests.
Current Infrastructure: Edge Migration
Status: ActiveBuilding and self-hosting the Dockerized application on an Azure VM was a massive success that provided invaluable hands-on systems experience. However, as the infrastructure evolved, we recognized a strategic opportunity to optimize our server compute. To free up our Azure environment for heavier backend services, we transitioned the documentation site to an edge-hosted model.
docker.unishdhungana.com.np domain remained intact with zero client downtime.