DEV Community

Cover image for Deploying a Complete 3-Tier Application with Jenkins: A Comprehensive Guide
Avesh
Avesh

Posted on

Deploying a Complete 3-Tier Application with Jenkins: A Comprehensive Guide

Deploying a 3-tier application (comprising presentation, application, and database layers) using Jenkins can significantly streamline the CI/CD process, ensuring consistency and automating every step from code to deployment. In this article, we’ll cover new strategies and approaches for deploying a complete 3-tier application using Jenkins, providing detailed steps, configurations, and code examples.

Introduction to 3-Tier Architecture

A 3-tier architecture is a software design pattern that consists of three primary layers:

  1. Presentation Layer (Frontend): This is the user interface, often a web or mobile app.
  2. Application Layer (Backend): The logic layer that processes data between the frontend and the database.
  3. Data Layer (Database): The database server where data is stored and managed.

Using Jenkins to automate the deployment of each layer, we’ll incorporate best practices for managing code, building the application, deploying across environments, and ensuring high availability and scalability.


Prerequisites

  1. Jenkins Installed: A Jenkins instance with pipeline capabilities (either via Jenkins Pipeline or Blue Ocean).
  2. Containerization Tools: Docker and Docker Compose for managing containerized environments.
  3. Infrastructure as Code (IaC): Terraform or Ansible to provision and configure the infrastructure.
  4. Git Repository: To host the application code and Jenkins pipeline scripts.
  5. Cloud Provider Account: AWS, Azure, or GCP for managing resources like virtual machines, databases, and load balancers.
  6. Access to Database and Application Credentials: Credentials for accessing and managing database and application resources.

Step 1: Setting Up Jenkins Pipeline

Defining the Jenkins Pipeline

To manage and deploy a 3-tier architecture, we’ll set up a Jenkins pipeline with stages for each application layer. Each layer (frontend, backend, and database) will have its build and deployment stages. Below is a sample Jenkinsfile that provides the initial pipeline structure.

pipeline {
    agent any

    environment {
        FRONTEND_IMAGE = 'frontend-app:latest'
        BACKEND_IMAGE = 'backend-app:latest'
        DATABASE_IMAGE = 'database-app:latest'
    }

    stages {
        stage('Checkout Code') {
            steps {
                checkout scm
            }
        }

        stage('Build Frontend') {
            steps {
                script {
                    sh 'docker build -t $FRONTEND_IMAGE ./frontend'
                }
            }
        }

        stage('Build Backend') {
            steps {
                script {
                    sh 'docker build -t $BACKEND_IMAGE ./backend'
                }
            }
        }

        stage('Deploy Database') {
            steps {
                script {
                    sh 'docker run -d --name db -e MYSQL_ROOT_PASSWORD=my-secret-pw $DATABASE_IMAGE'
                }
            }
        }

        stage('Deploy Backend') {
            steps {
                script {
                    sh 'docker run -d --name backend --link db -e DB_HOST=db $BACKEND_IMAGE'
                }
            }
        }

        stage('Deploy Frontend') {
            steps {
                script {
                    sh 'docker run -d --name frontend -p 80:80 $FRONTEND_IMAGE'
                }
            }
        }
    }

    post {
        always {
            echo 'Cleaning up...'
            sh 'docker rm -f $(docker ps -aq)'
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

This Jenkinsfile outlines the following stages:

  • Checkout Code: Retrieves the code from the Git repository.
  • Build Frontend: Builds the Docker image for the frontend.
  • Build Backend: Builds the Docker image for the backend.
  • Deploy Database: Deploys the database using Docker.
  • Deploy Backend: Deploys the backend application, linking it to the database.
  • Deploy Frontend: Deploys the frontend and exposes it on port 80.

Step 2: Automating Infrastructure Setup with Terraform

For a complete 3-tier architecture, we’ll use Infrastructure as Code (IaC) to provision the required infrastructure on AWS.

Example: Terraform Configuration

  1. Define Provider:

    # main.tf
    provider "aws" {
      region = "us-east-1"
    }
    
  2. Create Networking Components:

    # VPC, Subnets, and Security Groups
    resource "aws_vpc" "app_vpc" {
      cidr_block = "10.0.0.0/16"
    }
    
    resource "aws_subnet" "public_subnet" {
      vpc_id     = aws_vpc.app_vpc.id
      cidr_block = "10.0.1.0/24"
    }
    
  3. Deploy Database:

    # RDS Configuration for Database Layer
    resource "aws_db_instance" "app_db" {
      allocated_storage    = 20
      engine               = "mysql"
      engine_version       = "8.0"
      instance_class       = "db.t2.micro"
      name                 = "appdb"
      username             = "admin"
      password             = "adminpassword"
      skip_final_snapshot  = true
      vpc_security_group_ids = [aws_security_group.db_sg.id]
      db_subnet_group_name = aws_db_subnet_group.app_db_subnet_group.name
    }
    
  4. Deploy Application Layer (Backend) and Frontend Layer (Web Server):

    Use Elastic Beanstalk or EC2 instances to host the backend and frontend services, depending on your scalability and availability needs.


Step 3: Setting Up Docker Compose for Local Development

To simulate and manage the 3-tier application locally, use Docker Compose. This tool allows you to define and run multi-container applications.

Docker Compose Configuration

Create a docker-compose.yml file in the project root:

version: '3'
services:
  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: rootpassword
      MYSQL_DATABASE: mydb
    networks:
      - app-network

  backend:
    build: ./backend
    environment:
      DB_HOST: db
    networks:
      - app-network

  frontend:
    build: ./frontend
    ports:
      - "80:80"
    networks:
      - app-network

networks:
  app-network:
    driver: bridge
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • Database: The db service uses MySQL with an environment variable for the root password.
  • Backend: The backend connects to the database using DB_HOST.
  • Frontend: Exposes the frontend on port 80.

Running docker-compose up will start all services, allowing you to develop and test the 3-tier application locally.


Step 4: Integrating Jenkins with Docker Compose for Deployment

For deploying Docker Compose configurations through Jenkins, define an additional Jenkins pipeline stage to trigger the docker-compose commands.

stage('Deploy with Docker Compose') {
    steps {
        sh 'docker-compose -f docker-compose.yml up -d'
    }
}
Enter fullscreen mode Exit fullscreen mode

This stage deploys the 3-tier application by running Docker Compose in detached mode. Ensure Docker and Docker Compose are installed on the Jenkins agent.


Step 5: Configuring Rollback and Cleanup Strategies

For a robust deployment process, configure rollback strategies in case of deployment failures.

Rollback Example in Jenkins Pipeline

If a deployment stage fails, you can define a failure block in Jenkins to trigger a rollback.

post {
    failure {
        echo 'Rolling back to previous version...'
        sh 'docker-compose -f docker-compose.yml down && docker-compose -f docker-compose.previous.yml up -d'
    }
}
Enter fullscreen mode Exit fullscreen mode

Here, docker-compose.previous.yml defines the last stable configuration, allowing Jenkins to roll back automatically if a new deployment fails.

Cleanup of Resources

Cleaning up resources helps manage costs and prevent resource conflicts. Add a cleanup stage to remove Docker containers after testing or deployment.

stage('Cleanup') {
    steps {
        sh 'docker-compose down'
        sh 'docker system prune -f'
    }
}
Enter fullscreen mode Exit fullscreen mode

This step stops the containers and removes unused Docker objects.


Step 6: Setting Up Monitoring and Logging

Monitoring and logging ensure the application is running smoothly in production and provide data for troubleshooting when issues arise.

  1. Integrate Prometheus and Grafana:

    • Set up Prometheus to monitor container metrics (CPU, memory, network).
    • Use Grafana to visualize these metrics with dashboards.
  2. Add Centralized Logging with ELK Stack (Elasticsearch, Logstash, Kibana):

    • Configure Logstash to collect logs from each layer.
    • Visualize logs in Kibana, helping quickly identify issues.
  3. Configure Alerts:

    • Set up alerts in Grafana for metrics such as high CPU usage or container restarts.

Final Jenkins Pipeline Example for Complete 3-Tier Deployment

Below is a final version of the Jenkinsfile that includes deployment, rollback, and monitoring.

pipeline {
    agent any

    environment {
        FRONTEND_IMAGE = 'frontend-app:latest'
        BACKEND_IMAGE = 'backend-app:latest'
        DATABASE_IMAGE = 'database-app:latest'
    }

    stages {
        stage('Checkout') { steps { checkout scm } }

        stage('Build Frontend') {
            steps { sh 'docker build -t $FRONTEND_IMAGE ./frontend' }
        }

        stage('Build Backend') {
            steps { sh 'docker build -t $BACKEND_IMAGE ./backend

' }
        }

        stage('Deploy Database') {
            steps { sh 'docker-compose up -d db' }
        }

        stage('Deploy Backend') {
            steps { sh 'docker-compose up -d backend' }
        }

        stage('Deploy Frontend') {
            steps { sh 'docker-compose up -d frontend' }
        }

        stage('Deploy Monitoring') {
            steps { sh 'docker-compose -f monitoring.yml up -d' }
        }
    }

    post {
        failure {
            echo 'Deployment failed. Rolling back...'
            sh 'docker-compose -f docker-compose.previous.yml up -d'
        }
        always {
            sh 'docker system prune -f'
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

Deploying a 3-tier application with Jenkins involves setting up a pipeline that automates the build, deployment, and monitoring of each layer (frontend, backend, and database). By combining Docker, Docker Compose, and Infrastructure as Code, you can deploy a scalable and resilient application with minimal manual intervention. Integrate monitoring, logging, and rollback capabilities for a complete, production-ready deployment pipeline. This Jenkins pipeline approach can be further customized to suit different environments and specific application requirements, making it an adaptable and powerful DevOps solution.

Top comments (0)