Advanced DevOps Project: Full CI/CD Pipeline on Azure with Terraform, Docker, and Ansible

📌 Introduction
In today’s fast-paced cloud-native world, DevOps engineers are expected to not only understand automation and CI/CD but also to architect, deploy, and monitor production-grade infrastructures. This project showcases a full-scale DevOps pipeline that orchestrates a multi-tier web application on Microsoft Azure using a modern stack:
- Terraform for infrastructure as code
- Docker for containerization
- GitHub Actions for CI/CD automation
- Ansible for configuration management
- Prometheus & Grafana for monitoring and alerting
By the end of this tutorial, you’ll have built a resilient, scalable, and secure DevOps workflow deployable on real-world cloud environments.
🧱 Architecture Overview
Let’s visualize the overall design of this DevOps pipeline:
- Frontend: React application served via Docker container
- Backend: Node.js/Express API in a separate container
- Database: MongoDB container with volume persistence
- CI/CD: GitHub Actions building/pushing images to Azure Container Registry (ACR) and running Terraform + Ansible
- Monitoring: Prometheus and Grafana on a dedicated VM
- Infrastructure: Azure VNet, NSGs, Load Balancer, Virtual Machines
🔧 Step 1: Provisioning Azure Infrastructure with Terraform
Start by defining infrastructure as code using Terraform modules.
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "rg" {
name = "devops-rg"
location = "East US"
}
resource "azurerm_virtual_network" "vnet" {
name = "devops-vnet"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
}
Then add:
- Subnets for app and monitoring
- NSGs (Network Security Groups)
- Public IPs and Load Balancer
- Azure Container Registry
- Virtual Machines (Ubuntu)
🚢 Step 2: Dockerizing the Application
Create Dockerfiles for each component.
Dockerfile (backend):
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN npm install
EXPOSE 3000
CMD ["node", "server.js"]
Dockerfile (frontend):
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN npm install && npm run build
EXPOSE 80
CMD ["npx", "serve", "-s", "build"]
Dockerfile (MongoDB) is optional since we can use the official image from Docker Hub.
🔄 Step 3: GitHub Actions CI/CD Pipeline
Create .github/workflows/deploy.yml
:
name: CI/CD Pipeline
on:
push:
branches: [ main ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Log in to Azure
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Build Docker Images
run: |
docker build -t frontend ./frontend
docker build -t backend ./backend
- name: Push to ACR
run: |
az acr login --name myacr
docker tag frontend myacr.azurecr.io/frontend:latest
docker push myacr.azurecr.io/frontend:latest
- name: Terraform Init & Apply
run: |
cd infrastructure
terraform init
terraform apply -auto-approve
🔐 Don’t forget to store secrets like
AZURE_CREDENTIALS
safely in GitHub Secrets.
⚙️ Step 4: Automating Server Setup with Ansible
Once Terraform creates the VMs, use Ansible to configure them.
Inventory file:
[webservers]
10.0.1.4 ansible_user=azureuser
Playbook (deploy.yml):
- hosts: webservers
become: yes
tasks:
- name: Install Docker
apt:
name: docker.io
state: present
- name: Pull App Images from ACR
shell: docker pull myacr.azurecr.io/frontend:latest
- name: Run Frontend Container
docker_container:
name: frontend
image: myacr.azurecr.io/frontend:latest
state: started
ports:
- "80:80"
📊 Step 5: Monitoring with Prometheus & Grafana
Provision a dedicated VM for monitoring. SSH into it and install:
- Prometheus for metrics collection
- Node Exporter on all VMs
- Grafana for dashboards
Install Prometheus:
sudo useradd --no-create-home prometheus
wget https://github.com/prometheus/prometheus/releases/latest/download/prometheus-*.tar.gz
Prometheus config (prometheus.yml):
scrape_configs:
- job_name: 'node_exporter'
static_configs:
- targets: ['10.0.1.4:9100', '10.0.1.5:9100']
Grafana Dashboards: Import pre-built dashboards for Docker, node metrics, etc.
🔐 Step 6: Security Best Practices
- Use SSH key pairs for VM access
- Use GitHub secrets for tokens and credentials
- Create separate service principals for Terraform and ACR
- Apply NSG rules to only allow necessary ports (80, 443, 22)
- Configure auto-updates on VMs
🧠 Conclusion
This advanced DevOps project demonstrates a real-world, production-ready workflow covering everything from infrastructure provisioning to continuous deployment and monitoring. You can extend this further with:
- SSL termination using NGINX + Let’s Encrypt
- Horizontal pod scaling via AKS (Azure Kubernetes Service)
- Advanced alerting via Alertmanager or Azure Monitor
If you’re looking to impress recruiters, showcase your skillset in a portfolio, or solidify your DevOps knowledge, replicating (and customizing) this pipeline will give you a major edge.