Jenkins Project: Building CI/CD Pipeline for Scalable Web Applications
Single Server Deployment
Configuring Pipeline
In this guide, we set up a Jenkins pipeline for continuous integration and deployment (CI/CD). The pipeline performs essential tasks such as testing, packaging, transferring the package to a production server, installing necessary dependencies, and restarting the Flask application. Before diving into the Jenkinsfile configuration, review the overall pipeline workflow.
The pipeline consists of the following steps:
- Check out the code from Git.
- Install all required dependencies.
- Run tests using pytest.
- Package the application into a ZIP file.
- Transfer the packaged code to the production server.
- Connect to the production server to install dependencies.
- Restart the Flask application with a command like
systemctl restart flaskapp.service
.
Note
Ensure SSH access to the production server is available. The Jenkins server must be configured with the appropriate SSH credentials for secure connectivity.
Configuring Jenkins Credentials
To securely connect to the production server, set up two Jenkins credentials:
- An SSH key (e.g., the main.pem file from a previous demonstration).
- The production server IP address stored as a credential (this avoids hard-coding in the Jenkinsfile).
This configuration enables the Jenkinsfile to dynamically include these credentials.
The Jenkinsfile Configuration
Below is a complete example of a Jenkinsfile that sets up the environment, defines stages for building, testing, packaging, and deploying the application, and utilizes credentials safely. The production server IP is stored in an environment variable and used together with separate SSH credentials to copy files and execute remote commands.
Environment Variable Setup
The following snippet demonstrates how to store the production server IP as an environment variable using Jenkins credentials:
pipeline {
agent any
environment {
SERVER_IP = credentials('prod-server-ip')
}
// Additional stages will follow
}
Build, Test, and Package Stages
The next section installs dependencies, runs tests, and packages the code into a ZIP file, excluding unnecessary files such as the Git directory:
pipeline {
agent any
environment {
SERVER_IP = credentials('prod-server-ip')
}
stages {
stage('Setup') {
steps {
sh "pip install -r requirements.txt"
}
}
stage('Test') {
steps {
sh "pytest"
}
}
stage('Package Code') {
steps {
sh "zip -r myapp.zip ./* -x '*.git*'"
sh "ls -lart"
}
}
// The deployment stage will be defined next
}
}
Deployment Stage
In the deployment stage, the pipeline securely transfers the packaged code to the production server and executes commands remotely via SSH. The commands unzip the package, activate the Python virtual environment, install production dependencies, and restart the Flask application.
pipeline {
agent any
environment {
SERVER_IP = credentials('prod-server-ip')
}
stages {
// Setup, Test, and Package Code stages are defined above...
stage('Deploy to Prod') {
steps {
withCredentials([sshUserPrivateKey(credentialsId: 'ssh-key', keyFileVariable: 'MY_SSH_KEY', usernameVariable: 'username')]) {
sh '''
scp -i $MY_SSH_KEY -o StrictHostKeyChecking=no myapp.zip ${username}@${SERVER_IP}:/home/ec2-user/
ssh -i $MY_SSH_KEY -o StrictHostKeyChecking=no ${username}@${SERVER_IP} << EOF
unzip -o /home/ec2-user/myapp.zip -d /home/ec2-user/app/
source /home/ec2-user/app/venv/bin/activate
cd /home/ec2-user/app/
pip install -r requirements.txt
sudo systemctl restart flaskapp.service
EOF
'''
}
}
}
}
}
Key Points
- The
scp
command securely transfers themyapp.zip
file to the production server. - The
ssh
command logs into the production server using the same SSH key and executes a sequence of commands separated by a heredoc (<< EOF
). - Ensure that spacing and indentation between
EOF
markers are consistent to prevent issues.
This example highlights a straightforward approach to deploying your code with a Jenkins pipeline. Depending on your production environment, you may choose to store these commands in a separate script on the production server and execute that script via Jenkins for enhanced maintainability.
By following this structured methodology, you can build a robust and secure CI/CD pipeline while keeping your Jenkinsfile clean and manageable.
Further Reading
Happy coding!
Watch Video
Watch video content