DevOps

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.

Join our newsletter for powerful topics & updates

* indicates required

Intuit Mailchimp

Mohamed Assem

I'm Mohamed Assem, an IT professional with over 14 years of experience. I've worked extensively in infrastructure and server management, as well as software development, particularly with .NET technologies. Currently, I combine both skill sets in my role as a DevOps and Automation Engineer. Through my website, I aim to share my knowledge and make the field more accessible for beginners, helping them navigate the complexities of IT with ease

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button