Jenkins Freestyle Project for DevOps Engineers #Day-23
A Guide to Jenkins Freestyle Projects for DevOps Professionals
What is CI/CD?
CI (Continuous Integration) is the practice of automating the integration of code changes from multiple developers into a single codebase. It involves developers frequently committing their work into a central code repository (such as GitHub or Stash). Automated tools then build the newly committed code and perform tasks like code review, ensuring that the code is integrated smoothly. The key goals of Continuous Integration are to find and address bugs quickly, make the integration process easier across a team of developers, improve software quality, and reduce the time it takes to release new features.
CD (Continuous Delivery) follows Continuous Integration and ensures that new changes can be released to customers quickly and without errors. This includes running integration and regression tests in a staging environment (similar to production) to ensure the final release is stable. Continuous Delivery automates the release process, ensuring a release-ready product at all times and allowing deployment at any moment.
What Is a Build Job?
A Jenkins build job contains the configuration for automating specific tasks or steps in the application building process. These tasks include gathering dependencies, compiling, archiving, transforming code, testing, and deploying code in different environments.
Jenkins supports several types of build jobs, such as freestyle projects, pipelines, multi-configuration projects, folders, multibranch pipelines, and organization folders.
What is a Freestyle Project?
A freestyle project in Jenkins is a type of project that allows you to build, test, and deploy software using various options and configurations. Here are a few tasks you could complete with a freestyle project in Jenkins:
Task 1
Create an agent for your app (which you deployed using Docker in a previous task).
Create a new Jenkins freestyle project for your app.
In the "Build" section of the project, add a build step to run the
docker build
command to build the image for the container.Add a second step to run the
docker run
command to start a container using the image created in the previous step.
Step 1: Create an Agent for Your App
Create a Dockerfile for Your App
Ensure you have aDockerfile
in your application's root directory that specifies how to build your app's Docker image. Here’s an example of a simpleDockerfile
:FROM python:3.9-slim WORKDIR /app COPY . /app RUN pip install -r requirements.txt CMD ["python", "app.py"]
Build the Docker Image Manually (Optional)
You can manually test building the Docker image to ensure theDockerfile
works as expected. This step is optional but useful for verifying the Docker configuration.docker build -t my-app .
Step 2: Set Up Jenkins Freestyle Project
Access Jenkins Dashboard
Log into your Jenkins instance.Create a New Freestyle Project
Click on "New Item" in the Jenkins dashboard.
Enter a name for your project, e.g.,
MyApp-Docker-Build
.Select "Freestyle project" and click "OK".
Configure Source Code Management (Optional)
If your code is stored in a version control system like Git, configure the source code management to pull the code.
Add the repository URL and credentials, if needed.
Step 3: Add Build Steps
Build the Docker Image
In the "Build" section, click on "Add build step" and select "Execute shell".
Add the command to build the Docker image:
docker build -t my-app .
Run the Docker Container
Add another build step by clicking "Add build step" and selecting "Execute shell" again.
Add the command to run the Docker container:
docker run -d --name my-app-container -p 8000:8000 my-app
-d
: Run the container in detached mode (in the background).--name my-app-container
: Name the container.-p 8000:8000
: Map the container's port 8000 to the host's port 8000.my-app
: The name of the Docker image created in the previous step.
Step 4: Save and Run the Jenkins Job
Save the Configuration
- Click "Save" to save your Jenkins project configuration.
Build the Project
Go back to the Jenkins dashboard and click "Build Now" to run the job.
Monitor the console output to ensure the Docker image is built and the container is started successfully.
Step 5: Verify
Check Docker Containers
After the build, check if the container is running by executing:
docker ps
Access Your Application
- Open a web browser and go to
http://<your-server-ip>:8000
to access your app.
- Open a web browser and go to
Jenkinsfile (Groovy Script)
pipeline {
agent any
stages {
stage('Build Docker Image') {
steps {
script {
// Build the Docker image
sh 'docker build -t my-app .'
}
}
}
stage('Run Docker Container') {
steps {
script {
// Stop and remove the container if it already exists
sh '''
docker rm -f my-app-container || true
'''
// Run the Docker container
sh 'docker run -d --name my-app-container -p 8000:8000 my-app'
}
}
}
}
post {
always {
// Clean up unused Docker images and containers (optional)
sh 'docker system prune -f'
}
}
}
Explanation:
pipeline: Defines the start of the Jenkins pipeline.
agent any: The pipeline can run on any available agent/node.
stages: Contains different stages of the pipeline.
Stage 1: Build Docker Image:
- sh 'docker build -t my-app .': Runs the Docker build command to create a Docker image tagged as
my-app
.
- sh 'docker build -t my-app .': Runs the Docker build command to create a Docker image tagged as
Stage 2: Run Docker Container:
sh 'docker rm -f my-app-container || true': This command stops and removes any existing container with the name
my-app-container
if it exists. The|| true
ensures that the pipeline doesn’t fail if the container doesn't exist.sh 'docker run -d --name my-app-container -p 8000:8000 my-app': Runs a new Docker container named
my-app-container
in detached mode, mapping port 8000 of the container to port 8000 of the host.
post:
always: This block runs after the pipeline finishes, whether it passes or fails.
sh 'docker system prune -f': Cleans up unused Docker images and containers to free up space (optional step).
Usage Instructions:
Create a Jenkins Pipeline Project:
Go to Jenkins, click on "New Item," and select "Pipeline."
Name your project and proceed.
Add the Groovy Script:
- In the project configuration, under the "Pipeline" section, paste the above Groovy script.
Save and Run:
- Save the configuration and click "Build Now" to run the pipeline.
This Groovy script will automate the process of building and running a Docker container using Jenkins.
Task 2
Create a Jenkins project to run the
docker-compose up -d
command to start multiple containers defined in the compose file (Hint: use the application and database docker-compose file from Day 19).Set up a cleanup step in the Jenkins project to run the
docker-compose down
command to stop and remove the containers defined in the compose file.
Step 1: Prepare the Docker Compose File
Ensure you have a docker-compose.yml
file that defines your application and database containers. Here's an example docker-compose.yml
for reference:
version: '3'
services:
app:
image: my-app
ports:
- "8000:8000"
depends_on:
- db
db:
image: postgres:latest
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: mydatabase
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:
Step 2: Create a Jenkins Pipeline Project
Access Jenkins Dashboard
Log into your Jenkins instance.Create a New Pipeline Project
Click on "New Item" in the Jenkins dashboard.
Enter a name for your project, e.g.,
MyApp-DockerCompose
.Select "Pipeline" and click "OK".
Configure the Pipeline
Scroll down to the "Pipeline" section.
Choose "Pipeline script" from the definition dropdown.
In the script box, add the following Groovy script:
Jenkinsfile (Groovy Script)
pipeline {
agent any
stages {
stage('Start Docker Compose') {
steps {
script {
// Navigate to the directory containing the docker-compose.yml
dir('/path/to/your/docker-compose-directory') {
// Start the containers in detached mode
sh 'docker-compose up -d'
}
}
}
}
}
post {
always {
script {
// Clean up the Docker containers and networks
dir('/path/to/your/docker-compose-directory') {
sh 'docker-compose down'
}
}
}
}
}
Explanation:
pipeline: Defines the start of the Jenkins pipeline.
agent any: The pipeline can run on any available agent/node.
stages: Contains different stages of the pipeline.
Stage 1: Start Docker Compose:
dir('/path/to/your/docker-compose-directory'): Changes the working directory to the location of your
docker-compose.yml
file.sh 'docker-compose up -d': Runs
docker-compose up
in detached mode to start the services defined in thedocker-compose.yml
.
post:
always: This block runs after the pipeline finishes, whether it passes or fails.
sh 'docker-compose down': Stops and removes the containers, networks, and volumes defined in the
docker-compose.yml
.
Step 3: Usage Instructions
Replace the Directory Path:
- In the
dir('/path/to/your/docker-compose-directory')
line, replace/path/to/your/docker-compose-directory
with the actual path to yourdocker-compose.yml
file on the Jenkins server or node.
- In the
Save and Run:
Save the pipeline configuration.
Click "Build Now" to start the job.
Verify:
After the pipeline runs, you can check if the containers are up by running
docker ps
.The containers should be stopped and removed at the end of the pipeline.
Notes:
Ensure Docker and Docker Compose are installed and configured on the Jenkins agent where the pipeline will run.
The
docker-compose down
command in thepost
block ensures that the containers are cleaned up after the pipeline execution.
Wanderlust Three Tier Application Containerization
Deploying a MERN Stack Project Using Dockerfile and Docker-Compose with Jenkins Job Pipeline Trigger from Master on Agents node.
Pipeline Script
pipeline {
agent{
node{
label "PROD"
}
}
stages {
stage('Code Clone from GitHub: Step-1') {
steps {
echo 'Cloning code from GitHub'
git url:'https://github.com/nikunjdevcloud/wanderlust.git', branch: 'devops'
}
}
stage('Code Build: Step-2') {
steps {
echo 'Building Docker image'
sh 'docker build -t wanderlust-back-node:v1 .'
echo 'Backend Docker image build done.'
sh 'docker build -t wanderlust-front-react:v2 .'
echo 'Frontend Docker image build done.'
}
}
stage('Image Push to Docker Hub: Step-3') {
steps {
withCredentials([usernamePassword(
credentialsId: 'DockerHubCredentials',
passwordVariable: 'dockerHubPass',
usernameVariable: 'dockerHubUser'
)]) {
echo 'Logging in to Docker Hub'
sh 'docker login -u ${dockerHubUser} -p ${dockerHubPass}'
echo 'Tagging Backend Docker image'
sh 'docker tag wanderlust-back-node:v1 ${dockerHubUser}/wanderlust-back-node:Backend'
echo 'Pushing Backend Docker image to Docker Hub'
sh 'docker push ${dockerHubUser}/wanderlust-back-node:Backend'
echo 'Tagging Frontend Docker image'
sh 'docker tag wanderlust-front-react:v2 ${dockerHubUser}/wanderlust-front-react:Frontend'
echo 'Pushing Frontend Docker image to Docker Hub'
sh 'docker push ${dockerHubUser}/wanderlust-back-node:Frontend'
echo 'Both Frontend and Backend Docker image Pushed to DockerHub Successfully Completed..!!'
}
}
}
stage('Deploy with Docker Compose') {
steps {
echo 'Deploying with Docker Compose'
sh 'docker-compose down'
sh 'docker-compose up -d'
}
}
}
}
***************************************
Load distributed on each node by steps.
***************************************
pipeline {
agent none
stages {
stage('Code Clone from GitHub: Step-1') {
agent { label 'DEV' }
steps {
echo 'Cloning code from GitHub'
git url:'https://github.com/nikunjdevcloud/wanderlust.git', branch: 'devops'
}
}
stage('Code Build: Step-2') {
agent { label 'PROD' }
steps {
echo 'Building Docker image'
sh 'docker build -t wanderlust-back-node:v1 .'
echo 'Backend Docker image build done.'
sh 'docker build -t wanderlust-front-react:v2 .'
echo 'Frontend Docker image build done.'
}
}
stage('Image Push to Docker Hub: Step-3') {
agent { label 'QA' }
steps {
withCredentials([usernamePassword(
credentialsId: 'DockerHubCredentials',
passwordVariable: 'dockerHubPass',
usernameVariable: 'dockerHubUser'
)]) {
echo 'Logging in to Docker Hub'
sh 'docker login -u ${dockerHubUser} -p ${dockerHubPass}'
echo 'Tagging Backend Docker image'
sh 'docker tag wanderlust-back-node:v1 ${dockerHubUser}/wanderlust-back-node:Backend'
echo 'Pushing Backend Docker image to Docker Hub'
sh 'docker push ${dockerHubUser}/wanderlust-back-node:Backend'
echo 'Tagging Frontend Docker image'
sh 'docker tag wanderlust-front-react:v2 ${dockerHubUser}/wanderlust-front-react:Frontend'
echo 'Pushing Frontend Docker image to Docker Hub'
sh 'docker push ${dockerHubUser}/wanderlust-back-node:Frontend'
echo 'Both Frontend and Backend Docker image Pushed to DockerHub Successfully Completed..!!'
}
}
}
stage('Deploy with Docker Compose: Last-Step') {
agent { label 'DEV' }
steps {
echo 'Deploying with Docker Compose'
sh 'docker-compose down'
sh 'docker-compose up -d'
}
}
}
}
***************************************************************
Wanderlust Agent-1 Dev
Wonderlust agent dev environment.
Wanderlust Agent-2 Prod
Wonderlust agent Prod environment.
Wanderlust Agent-3 QA
Wonderlust agent QA environment.
Workspace Created:
/home/ubuntu/app
Conclusion
Jenkins Freestyle Projects offer DevOps engineers a flexible and powerful way to automate the build, test, and deployment processes of their applications. By leveraging Docker and Docker Compose within Jenkins, engineers can ensure consistent and reliable environments for their applications, streamline their CI/CD pipelines, and ultimately deliver high-quality software more efficiently. Whether you're building a simple application or managing complex microservices, Jenkins provides the tools and integrations necessary to support your DevOps practices and enhance your development workflow.
Connect and Follow:
Like👍 | Share📲 | Comment💭