Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 119 additions & 10 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,130 @@ pipeline {
steps {
script{
sh 'git --version'
}
}
}
} //script
} //steps
} //stage
stage('Checkout') {
steps {
git branch: "${env.BRANCH_NAME}", url: 'https://github.com/ADITYA1234556/docker-jenkins.git', credentialsId: 'github-token'
}
}
} //steps
} //stage
stage('Build Docker Image') {
steps {
script {
docker.build("${env.ECR_REPO}:${env.TAG}")
}
}
}
}
}
} //script
} //steps
} //stage
stage('Push to ECR') {
steps {
withAWS(credentials: 'aws-credentials', region: "${AWS_REGION}")
{
sh "aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${env.ECR_REPO}"
sh "docker push ${env.ECR_REPO}:${env.TAG}"
} //withAWS
} //steps
post {
success {
// Send email notification after successful image push to ECR
emailext(
subject: "Jenkins Job - Docker Image Pushed to ECR Successfully",
body: "Hello,\n\nThe Docker image '${env.IMAGE_NAME}:${env.TAG}' has been successfully pushed to ECR.\n\nBest regards,\nJenkins",
recipientProviders: [[$class: 'DevelopersRecipientProvider']],
to: "[email protected]"
)
} //success
} //post
} //stage
stage('Static Code Analysis - SonarQube') {
steps {
script {
withSonarQubeEnv('SonarQubeServer') {
sh 'mvn sonar:sonar -Dsonar.organization=aditya1234556'
} //withSonarQubeEnv
} //script
} //steps
} //stage

stage('Container Security Scan - Trivy') {
steps {
script {
sh "trivy --timeout 1m image ${ECR_REPO}:${TAG} > 'trivyscan.txt'"
} //script
} //steps
post {
success{
emailext(
subject: "Trivy scan result",
body: "Hello, \n Trivy scan result in attachment \n Best regards, \n Jenkins \n ",
recipientProviders: [[$class: 'DevelopersRecipientProvider']],
to: "[email protected]",
attachmentsPattern: 'trivyscan.txt'
)
} //success
} //post
} //stage

stage('Deploy to Environment test') {
steps {
sshagent(['ec2-ssh-key']) {
sh 'echo "Starting SSH connection test"'
sh 'ssh -tt -o StrictHostKeyChecking=no [email protected] ls'
} //sshagent
} //steps
} //stage

stage('Deploy to Environment') {
steps {
script {
def targetHost = ''
if (env.BRANCH_NAME == 'DEV') {
targetHost = '13.42.5.135'
} else if (env.BRANCH_NAME == 'STAGING') {
targetHost = '35.179.105.161'
} else if (env.BRANCH_NAME == 'PROD') {
targetHost = '35.179.95.72'
} else if (env.BRANCH_NAME == 'master') {
targetHost = '35.179.95.72'
}
withCredentials([usernamePassword(credentialsId: 'aws-ecr', usernameVariable: 'AWS_ACCESS_KEY_ID', passwordVariable: 'AWS_SECRET_ACCESS_KEY')]) {
sshagent(['ec2-ssh-key']){
sh """
ssh -tt -o StrictHostKeyChecking=no ubuntu@${targetHost} << EOF
aws ecr get-login-password --region eu-west-2 | docker login --username AWS --password-stdin ${env.ECR_REPO}
docker pull ${ECR_REPO}:${TAG}
docker stop ${IMAGE_NAME} || true
docker rm ${IMAGE_NAME} || true
docker run -d --name ${IMAGE_NAME} -p 8080:8080 -p 8090:8090 ${ECR_REPO}:${TAG}
exit 0
EOF
"""
} //withCredentials
} //sshagent
} //script
} //steps
} //stage (Deploy to Environment)
} //stages
post {
always {
cleanWs() // Clean up workspace after the build
} //always
success {
emailext(
subject: "Jenkins Job - Docker Image Pushed to ECR Successfully",
body: "Hello,\n\nThe Docker image '${env.IMAGE_NAME}:${env.TAG}' has been successfully pushed to ECR.\n\nBest regards,\nJenkins",
recipientProviders: [[$class: 'DevelopersRecipientProvider']],
to: "[email protected]"
)
} //success
failure {
emailext(
subject: "Jenkins Job - Failure Notification",
body: "Hello,\n\nThe Jenkins job failed during the process. Please check the logs for details.\n\nBest regards,\nJenkins",
recipientProviders: [[$class: 'DevelopersRecipientProvider']],
to: "[email protected]"
)
} //failure
} //post
} //pipeline

44 changes: 43 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,46 @@
- Under Build Configuration, set it to by Jenkinsfile

4. **Define Jenkinsfile with Email Notification Step**
-
- In the Jenkinsfile replace the Environment variables with yours.
- Configure correct login details in Manage Jenkins -> Credentials -> add the following credentials
- Sonarqube token ('sonartoken')
- Github-Token
- AWS CLI Access key and Secret access key ('aws-ecr')
- Private SSH key pair for EC2 instance ('ec2-ssh-key')
- Gmail Username and App password ('gmailcreds')
- Add the following in Manage Jenkins -> System
- Sonarqube server details -> pass the authentication details -> (Name: 'SonarQubeServer', Auth token: 'sonartoken')
- E-mail Notification -> pass the authentication details -> ('gmailcreds')
- Install trivy on worker machines
```bash
wget https://github.com/aquasecurity/trivy/releases/download/v0.57.0/trivy_0.57.0_Linux-64bit.deb
sudo dpkg -i trivy_0.57.0_Linux-64bit.deb
trivy --version
trivy --timeout 10m image imagename
```
- The timeout will make sure trivy command gets enough time to download the dependencies
- Create 3 EC2 instances for different environments and pass their IP addresses in stage('Deploy to Environment')
- Install awscli on these instances because we will use awscli command to talk to AWS ECR to get a temporary token
```bash
# aws ecr gets a temporary token from aws in eu-west-2 which will be used by docker without rquiring permanent creds
# docker login --username AWS --password-stdin //temporary token ${ECRREPO}
aws ecr get-login-password --region eu-west-2 | docker login --username AWS --password-stdin ${env.ECR_REPO}
docker pull ${ECR_REPO}:${TAG}
docker stop ${IMAGE_NAME} || true
docker rm ${IMAGE_NAME} || true
docker run -d --name ${IMAGE_NAME} -p 8080:8080 -p 8090:8090 ${ECR_REPO}:${TAG}
```

## STEPS INVOLVED

1. **STAGE 1: Verify git on Agent machine**
2. **STAGE 2: Pull the source code from GitHub Repository.**
3. **STAGE 3: Build docker image based on the Dockerfile Configuration.**
1. The Dockerfile uses nginx as base image
2. Removes default nginx configuration and replaces with our custom configuration
3. Copies application code from directories app1 and app2 and places them on nginx/html/
4. Builds docker image exposing 2 ports 8080 and 8090
4. **STAGE 4: To push the docker image that was build in the previous step to amazon ECR and send an email notification.**
5. **STAGE 5: Sonarqube server scans the project code for any vulnerabilities if test passes according to QUALITY GATE criteria on Sonarqube pipeline moves to next stage.**
6. **STAGE 6: We do a trivy scan on the AMAZON ECR image and send a report in email.**
7. **STAGE 7: Deploy the AWS ECR image on different EC2 instances according to the Environment and from which branch the code was updated.**
29 changes: 29 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>uk.co.theaditya</groupId>
<artifactId>docker-jenkins</artifactId>
<version>1.0</version>
<packaging>jar</packaging>

<properties>
<!-- Add properties for SonarQube project configuration -->
<sonar.projectKey>uk.co.theaditya:docker-jenkins</sonar.projectKey>
<sonar.projectName>Docker Jenkins Website</sonar.projectName>
<sonar.projectVersion>1.0</sonar.projectVersion>
<sonar.organization>ADITYA1234556</sonar.organization>
</properties>

<build>
<plugins>
<!-- SonarQube Maven Plugin -->
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>4.0.0.4121</version>
</plugin>
</plugins>
</build>
</project>