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:
- Presentation Layer (Frontend): This is the user interface, often a web or mobile app.
- Application Layer (Backend): The logic layer that processes data between the frontend and the database.
- 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
- Jenkins Installed: A Jenkins instance with pipeline capabilities (either via Jenkins Pipeline or Blue Ocean).
- Containerization Tools: Docker and Docker Compose for managing containerized environments.
- Infrastructure as Code (IaC): Terraform or Ansible to provision and configure the infrastructure.
- Git Repository: To host the application code and Jenkins pipeline scripts.
- Cloud Provider Account: AWS, Azure, or GCP for managing resources like virtual machines, databases, and load balancers.
- 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)'
}
}
}
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
-
Define Provider:
# main.tf provider "aws" { region = "us-east-1" }
-
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" }
-
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 }
-
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
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'
}
}
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'
}
}
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'
}
}
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.
-
Integrate Prometheus and Grafana:
- Set up Prometheus to monitor container metrics (CPU, memory, network).
- Use Grafana to visualize these metrics with dashboards.
-
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.
-
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'
}
}
}
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)