Skip to content

sandeep-ssh/nginx-node-redis-az1

Repository files navigation

🚀 CI/CD with Terraform & GitHub Actions on Azure

Deploying a Node.js + Redis Application (Azure‑only)

Focus: Azure architecture fundamentals, DevOps maturity, Infrastructure as Code, and production‑grade thinking


🏗️ Architecture Overview (Azure Well‑Architected)

Azure Architecture Diagram


🧱 Azure Well‑Architected Framework Alignment

Pillar How It’s Addressed
Operational Excellence CI/CD automation, reproducible Terraform plans
Security Network Security Groups, Service Principal, least privilege
Reliability Redundant Node.js containers, stateless app tier
Performance Efficiency NGINX load distribution, lightweight containers
Cost Optimization Single environment, automated teardown via CI/CD

☁️ Azure Architecture Breakdown

Core Components

  • Terraform provisions all Azure infrastructure
  • Azure Virtual Network (VNet) provides network isolation
  • Docker runs all workloads on the host
  • NGINX acts as reverse proxy and load distributor
  • Two Node.js containers (web1, web2) provide redundancy
  • Redis container maintains shared request state
  • GitHub Actions automates deployment and teardown

Traffic flows: Internet → NGINX → Node.js containers → Redis


🎯 What This Project Demonstrates

This project demonstrates end-to-end Azure cloud engineering ownership using first principles.

  • Designed and deployed a production-style Azure architecture using Terraform (IaC)
  • Built a real CI/CD pipeline with GitHub Actions (build → provision → deploy)
  • Used Docker + NGINX + Redis to show strong container fundamentals before orchestration
  • Made intentional architectural trade-offs (avoided AKS to reduce complexity and cost)
  • Treated infrastructure and application code as versioned, repeatable, and auditable
  • Showcased DevOps maturity: automation, scalability thinking, and operational clarity

🧭 Executive Summary

This repository demonstrates an end‑to‑end DevOps workflow on Microsoft Azure using Terraform, Docker, and GitHub Actions.

A simple Node.js + Redis request‑counter application is used to showcase:

  • Infrastructure as Code on Azure
  • CI/CD‑driven infrastructure lifecycle
  • Container‑based application design
  • Clear architectural trade‑offs aligned with the Azure Well‑Architected Framework

The application is intentionally simple. The value lies in how it is built, deployed, automated, and evolved.

Design Intent

  • No PaaS abstractions or managed load balancers
  • Single Azure environment to avoid premature complexity
  • Reverse proxy for traffic control
  • Horizontally scalable application tier
  • Shared state managed explicitly

This mirrors how many real systems start simple and evolve responsibly.


☁️ Azure Architecture Breakdown

Core Components

  • Terraform provisions all Azure infrastructure
  • Azure Virtual Network (VNet) provides network isolation
  • Docker runs all workloads on the host
  • NGINX acts as reverse proxy and load distributor
  • Two Node.js containers (web1, web2) provide redundancy
  • Redis container maintains shared request state
  • GitHub Actions automates deployment and teardown

Traffic flows: Internet → NGINX → Node.js containers → Redis


🧠 Application Concept

A Request Counter application that:

  • Increments a global counter stored in Redis

  • Displays:

    • Total request count
    • Hostname serving the request (web1 or web2)
  • Built with Node.js (Express)

  • Served through NGINX

  • Includes a clean, minimal HTML UI

This design demonstrates stateless services + shared state — a foundational cloud pattern.


🛠 Technology Stack

  • Terraform – Azure Infrastructure as Code
  • Docker & Docker Compose – Containerization
  • NGINX – Reverse proxy & traffic distribution
  • Node.js (Express) – Application layer
  • Redis – Shared state
  • GitHub Actions – CI/CD automation

🧪 Local Development

docker compose up --build
  • Builds all images
  • Starts Redis, Node.js apps, and NGINX
  • Application exposed on port 80

Visit:

http://localhost:80

⚙️ Terraform Deployment (Azure)

cd terra-config/azure
terraform init
terraform plan -out=tfplan
terraform apply -auto-approve tfplan

Terraform provisions:

  • Azure networking
  • Security rules
  • Compute host
  • Bootstrap configuration for Docker workloads

🔐 GitHub Actions Secrets (Azure)

Add the following secrets to your GitHub repository:

Secret Description
AZURE_CLIENT_ID Service Principal App ID
AZURE_CLIENT_SECRET Service Principal Secret
AZURE_TENANT_ID Azure AD Tenant ID
AZURE_SUBSCRIPTION_ID Azure Subscription ID

Path:

GitHub Repo → Settings → Secrets → Actions

🔄 CI/CD Workflow

  1. Developer pushes code

  2. GitHub Actions pipeline triggers

  3. Pipeline:

    • Validates Terraform
    • Provisions Azure infrastructure
    • Deploys containers
    • Optionally destroys resources
  4. Application becomes available automatically

This mirrors real‑world DevOps delivery pipelines.


🧩 Key Components

web/server.js

  • Connects to Redis on port 6379
  • Increments and displays request count
  • Displays hostname of serving container
  • Runs on port 5000

nginx/nginx.conf

  • Reverse proxy configuration
  • Load balances traffic across Node.js containers

docker-compose.yml

  • Redis container
  • Two Node.js containers
  • NGINX container

terra-config/azure

  • Azure‑specific Terraform configuration
  • Networking and security
  • Docker bootstrap via cloud‑init

🔮 Future Enhancements

Azure Infrastructure

  • VM Scale Sets for horizontal scaling
  • Azure Load Balancer or Application Gateway
  • Azure Cache for Redis (managed)
  • Azure DNS for custom domains

Container Orchestration

  • Migration to AKS
  • Kubernetes Deployments & Services
  • Horizontal Pod Autoscaling

Security

  • Managed Identity instead of secrets
  • Azure Key Vault integration
  • TLS with Azure Certificates

CI/CD & Quality

  • Terraform linting & policy checks
  • Multi‑environment pipelines (dev / prod)
  • Blue‑green or canary deployments

🌟 Why This Project Stands Out

  • Azure‑focused architecture clarity
  • Strong Infrastructure as Code fundamentals
  • CI/CD‑driven infrastructure lifecycle
  • Intentional simplicity with a clear growth path
  • Demonstrates system‑level thinking, not just tooling

This repository reflects how real Azure platforms are designed, delivered, and evolved.


🧠 TL;DR – Lessons Learned

  • Azure VM SKUs are not always available
    Valid VM sizes can fail at runtime due to regional capacity constraints (especially small B series in australiaeast).

  • Terraform cannot detect real-time Azure capacity
    A successful terraform plan does not guarantee terraform apply will succeed.

  • Simplicity beats clever Terraform logic
    Overengineering with dynamic SKUs and conditional logic increased failures. Keeping Terraform simple and moving retries to CI worked better.

  • CI/CD pipelines expose timing issues
    VM creation ≠ application readiness. Startup scripts, Docker installs, and containers need retries and wait logic.

  • Azure resource deletion is eventually consistent
    Networking resources (NICs, public IPs) may remain locked briefly after VM deletion, causing destroy failures.

  • Static resource names don’t work in CI/CD
    Re-runs and parallel executions require unique naming to avoid collisions.

  • Cloud-init and Docker failures are often silent
    Startup issues don’t always surface clearly in Terraform or CI logs.

  • Small VMs are not “reliably available”
    Popular low-cost SKUs are often the first to run out of capacity.

Key takeaway: Cloud infrastructure must be designed for failure and retries — not just correctness.

Why Not AKS?

This project deliberately avoids Azure Kubernetes Service (AKS) to demonstrate foundational cloud engineering judgment rather than managed-platform dependency.

Rationale

  • Docker on Azure Compute allows full control over networking, ingress, and deployment mechanics
  • Keeps the architecture understandable and debuggable for smaller teams
  • Demonstrates container fundamentals before orchestration abstraction
  • Mirrors real-world cost-conscious environments where AKS may be overkill

AKS is intentionally deferred as a future evolution, not a missing skill.


Architecture Decision Records (ADR)

Key architectural choices made in this project:

Decision Reasoning
Terraform for IaC Cloud-agnostic skills, repeatability, auditability
GitHub Actions Native GitHub integration, OIDC-ready, no secrets sprawl
Docker over VM apps Immutable builds, consistency across environments
NGINX as reverse proxy Simple, battle-tested ingress layer
Redis caching Stateless web tier, improved latency

CI/CD Flow (GitHub Actions)

  1. Code pushed to main
  2. GitHub Actions pipeline triggered
  3. Docker images built and tagged
  4. Terraform plan + apply executed
  5. Azure infrastructure provisioned/updated
  6. Containers deployed and traffic routed via NGINX

This pipeline demonstrates end-to-end automation from commit to production.

🏁 Final Reflection

Good DevOps is not about complexity — it’s about simplicity,clarity, automation, and disciplined evolution.

If this repository helped you, feel free to ⭐ star it, fork it, or extend it.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors