This project demonstrates a CI/CD pipeline for the Spring Petclinic application using Jenkins, Maven, SonarQube, Nexus, and Tomcat. The pipeline automates building, testing, code analysis, artifact storage, and deployment using Jenkins Pipeline as Code.
- Architecture
- Technologies Stack
- Prerequisites
- Infrastructure Setup
- Pipeline Stages
- Configuration Steps
- Jenkinsfile Explanation
- Future Enhancements
The project utilizes a modular, scalable architecture with three dedicated Virtual Machines (VMs):
- Jenkins VM:
- Orchestrates the entire CI/CD pipeline
- Runs build and test processes
- Hosts SonarQube (running as Docker container)
- Integrates with SonarQube and Nexus
- Nexus VM:
- Manages and stores build artifacts
- Provides artifact versioning and distribution
- Tomcat VM:
- Hosts the application server
- Receives and deploys the final WAR file
Category | Technology |
---|---|
CI/CD Platform | Jenkins |
Build System | Maven |
Code Analysis | SonarQube |
Artifact Repository | Nexus |
Application Server | Tomcat |
Testing Framework | JUnit |
Runtime | Java 17 |
The CI/CD pipeline follows these key stages:
- Git Checkout: Clone repository from GitHub
- Compile: Compile project using Maven
- Test: Run unit tests
- SonarQube Analysis: Analyze code quality
- Build: Package application as WAR
- Deploy to Nexus: Store artifacts
- Copy to Tomcat: Transfer WAR to server
- Deploy WebApp: Activate application
- Ubuntu/Debian-based system
- Docker and Docker Compose
- Java Development Kit 17
- Maven 3.8+
- Update system packages:
sudo apt update
- Install Jenkins:
sudo wget -O /usr/share/keyrings/jenkins-keyring.asc \
https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key
echo "deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc]" \
https://pkg.jenkins.io/debian-stable binary/ | sudo tee \
/etc/apt/sources.list.d/jenkins.list > /dev/null
sudo apt-get update
sudo apt-get install jenkins
- Download and install Nexus:
cd /opt
wget https://download.sonatype.com/nexus/3/latest-unix.tar.gz
tar -zxvf latest-unix.tar.gz
rm latest-unix.tar.gz
sudo mv nexus-3.* nexus
- Create systemd service:
sudo nano /etc/systemd/system/nexus.service
- Add configuration for Nexus service:
[Unit]
Description=nexus service
After=network.target
[Service]
Type=forking
LimitNOFILE=65536
ExecStart=/opt/nexus/bin/nexus start
ExecStop=/opt/nexus/bin/nexus stop
Restart=on-abort
[Install]
WantedBy=multi-user.target
- Enable and start Nexus:
sudo systemctl enable nexus
sudo systemctl start nexus
- Get the default admin password:
cat /opt/nexus/sonatype-work/nexus3/admin.password
- Download and install Tomcat:
# Download and install Tomcat 11
wget https://dlcdn.apache.org/tomcat/tomcat-11/v11.0.2/bin/apache-tomcat-11.0.2.tar.gz
# Create service user
sudo useradd -r -m -U -d /opt/tomcat -s /bin/false tomcat
# Extract and configure
tar xzf apache-tomcat-11.0.2.tar.gz
sudo mv apache-tomcat-11.0.2/* /opt/tomcat/
# Set permissions
sudo chown -R tomcat: /opt/tomcat
- Configure Tomcat users (
/opt/tomcat/conf/tomcat-users.xml
):
<tomcat-users>
<role rolename="manager-gui" />
<user username="manager" password="password" roles="manager-gui" />
<role rolename="admin-gui" />
<user username="admin" password="password" roles="manager-gui,admin-gui" />
</tomcat-users>
- Create Tomcat service (
/etc/systemd/system/tomcat.service
):
[Unit]
Description=Apache Tomcat 11 Web Application Server
After=network.target
[Service]
Type=forking
User=tomcat
Group=tomcat
Environment="JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64"
Environment="CATALINA_HOME=/opt/tomcat"
Environment="CATALINA_BASE=/opt/tomcat"
Environment="CATALINA_PID=/opt/tomcat/temp/tomcat.pid"
Environment="CATALINA_OPTS=-Xms512M -Xmx1024M -server -XX:+UseParallelGC"
ExecStart=/opt/tomcat/bin/startup.sh
ExecStop=/opt/tomcat/bin/shutdown.sh
[Install]
WantedBy=multi-user.target
- Start Tomcat service:
sudo systemctl daemon-reload
sudo systemctl start tomcat
sudo systemctl status tomcat
Create docker-compose.yaml
:
services:
sonarqube:
image: sonarqube:lts-community
depends_on:
- sonar_db
environment:
SONAR_JDBC_URL: jdbc:postgresql://sonar_db:5432/sonar
SONAR_JDBC_USERNAME: sonar
SONAR_JDBC_PASSWORD: sonar
ports:
- "9000:9000"
sonar_db:
image: postgres:17.2-alpine3.21
environment:
POSTGRES_USER: sonar
POSTGRES_PASSWORD: sonar
POSTGRES_DB: sonar
Update ~/.m2/settings.xml
:
<server>
<id>deployment</id>
<username>username</username> <!-- Nexus username -->
<password>password</password> <!-- Nexus password -->
</server>
Update the pom.xml
with your Nexus Repository information:
<distributionManagement>
<repository>
<id>deployment</id>
<name>Internal Releases</name>
<url>http://<your-tomcat-server-ip>:8081/repository/spring-petclinic-release/</url>
</repository>
<snapshotRepository>
<id>deployment</id>
<name>Internal Snapshot Releases</name>
<url>http://<your-tomcat-server-ip>:8081/repository/spring-petclinic-snap/</url>
</snapshotRepository>
</distributionManagement>
- Access Nexus web interface
- Create Release Repository:
- Type: maven2 (hosted)
- Name: spring-petclinic-release
- Version Policy: Release
- Create Snapshot Repository:
- Type: maven2 (hosted)
- Name: spring-petclinic-snap
- Version Policy: Snapshot
Update the following in the Jenkinsfile:
REMOTE_USER
: Tomcat server usernameREMOTE_HOST
: Tomcat server hostnameREMOTE_PATH
: Temporary file transfer locationTOMCAT_PATH
: Tomcat webapps directory- SonarQube authentication token
After successful deployment to Nexus, you should see:
-
Release artifacts in the
spring-petclinic-release
repository: -
Snapshot artifacts in the
spring-petclinic-snap
repository:
The application deployment can be verified in two ways:
-
Through Tomcat Manager UI:
The
/spring-petclinic
application should be listed as "running" -
Accessing the Application:
The Spring PetClinic application interface should be accessible
- Docker containerization of all components
- Integrate additional security scanning
- Create staging and production environment deployments