đ Executive Summary
TL;DR: Automating Docker image vulnerability scanning is essential to mitigate security risks in containerized applications. This guide details integrating Trivy, a fast open-source scanner, with Jenkins CI/CD pipelines to automatically detect and fail builds based on critical vulnerabilities, shifting security left in the development process.
đŻ Key Takeaways
- Integrating Trivy into a Jenkins pipeline enables automated scanning of Docker images for vulnerabilities, providing immediate security feedback within the CI/CD process.
- The
trivy image âexit-code 1 âseverity HIGH,CRITICALcommand is crucial for configuring Jenkins to fail builds automatically upon detecting high or critical vulnerabilities. - Generating and archiving a JSON scan report (
trivy image âformat json âoutput scan-report.json) ensures comprehensive auditing and traceability of vulnerability findings, even if the build fails.
Monitor Docker Image Vulnerabilities with Trivy and Jenkins
Introduction
In the modern software development lifecycle, containerization with Docker has become the standard for building and deploying applications. While containers offer portability and consistency, they also introduce a new layer of security concerns. An image built from a vulnerable base image or containing outdated packages can expose your entire application to significant risks. Manually tracking these vulnerabilities is impractical and error-prone.
This is where automated security scanning becomes essential. By integrating a vulnerability scanner directly into your Continuous Integration/Continuous Deployment (CI/CD) pipeline, you can âshift left,â catching security issues early in the development process. This tutorial provides a comprehensive guide on integrating Trivy, a simple and fast open-source vulnerability scanner, with Jenkins to automate Docker image scanning. By the end, youâll have a pipeline that automatically scans your images and can fail a build if critical vulnerabilities are detected, ensuring a more secure deployment process.
Prerequisites
Before you begin, ensure you have the following set up and configured:
- A running Jenkins instance with the Pipeline plugin installed.
- A Jenkins agent (or the main Jenkins instance) with Docker installed and running.
- Appropriate permissions for the Jenkins user to execute Docker commands. Typically, this involves adding the âjenkinsâ user to the âdockerâ group.
- A Docker image to scan, either locally built or hosted in a registry like Docker Hub. For this tutorial, we will use a public image for demonstration.
Step-by-Step Guide
Step 1: Install Trivy on Your Jenkins Agent
First, Trivy must be available on the Jenkins agent where your pipeline stages will execute. Trivy is a single binary, which makes installation straightforward. We will download the latest release from its official repository and place it in a directory that is part of the systemâs PATH, like a userâs local bin directory.
You can add a âSetupâ stage in your Jenkins pipeline to perform this installation on-the-fly, or you can pre-install it on your agent machine. Here is a command to install Trivy on a Linux-based agent:
# Bash Script
# This script downloads and installs Trivy into a user-accessible binary directory.
# Replace VERSION and ARCH with the appropriate values for your system.
export TRIVY_VERSION="0.48.1"
export ARCH="64bit"
export OS="Linux"
# Download the tarball
curl -LO https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VERSION}/trivy_${TRIVY_VERSION}_${OS}-${ARCH}.tar.gz
# Extract and install
tar zxvf trivy_${TRIVY_VERSION}_${OS}-${ARCH}.tar.gz
install trivy /home/jenkins/bin/trivy
Explanation: This script downloads the specified Trivy version, extracts the binary from the archive, and then uses the install command to place it in /home/jenkins/bin/. Ensure this directory is included in your Jenkins userâs $PATH environment variable so the trivy command can be called directly.
Step 2: Create a New Jenkins Pipeline Job
Now, letâs create a Jenkins job that will orchestrate the image build and scan process. In your Jenkins dashboard:
- Click on New Item.
- Enter a name for your job (e.g., âdocker-vulnerability-scanâ).
- Select Pipeline and click OK.
- Scroll down to the Pipeline section. You can write your script directly in the text area (choosing âPipeline scriptâ) or pull it from a
Jenkinsfilein your SCM.
For this tutorial, we will use the âPipeline scriptâ option and paste our script directly into the Jenkins UI.
Step 3: Define the Pipeline with a Trivy Scan Stage
The core of our automation is the Jenkinsfile. This declarative pipeline script defines all the stages our CI process will execute. We will include a placeholder âBuildâ stage and a dedicated âVulnerability Scanâ stage.
Copy the following pipeline script into your Jenkins job configuration:
// Jenkinsfile (Declarative Pipeline)
pipeline {
agent any
environment {
// Define the image to scan. This can be parameterized.
DOCKER_IMAGE = 'python:3.9-slim'
}
stages {
stage('Pull Image for Scanning') {
steps {
script {
echo "Pulling image: ${DOCKER_IMAGE}"
sh "docker pull ${DOCKER_IMAGE}"
}
}
}
stage('Vulnerability Scan') {
steps {
script {
echo "Scanning ${DOCKER_IMAGE} for vulnerabilities..."
// Fail the build if any HIGH or CRITICAL vulnerabilities are found.
// The --exit-code flag is crucial for pipeline control.
sh "trivy image --exit-code 1 --severity HIGH,CRITICAL ${DOCKER_IMAGE}"
}
}
}
stage('Generate and Archive Report') {
steps {
script {
echo "Generating JSON report for ${DOCKER_IMAGE}..."
// Generate a report regardless of vulnerabilities for auditing.
// The '|| true' ensures this step doesn't fail the pipeline if Trivy returns a non-zero exit code.
sh "trivy image --format json --output scan-report.json ${DOCKER_IMAGE} || true"
}
archiveArtifacts artifacts: 'scan-report.json', allowEmptyArchive: true
}
}
}
post {
always {
echo 'Scan complete. Cleaning up...'
// Clean up the downloaded image to save space on the agent.
sh "docker rmi ${DOCKER_IMAGE} || true"
}
}
}
Explanation of the Jenkinsfile:
-
agent any: This tells Jenkins to run the pipeline on any available agent. -
environment: We define theDOCKER\_IMAGEvariable here. In a real-world scenario, this would likely be the image you just built (e.g.,my-app:1.2.${env.BUILD\_NUMBER}). -
stage(âPull Image for Scanningâ): Before scanning, we ensure the image is available on the agent by pulling it from a registry. If you were building the image in a previous stage, this step would not be necessary. -
stage(âVulnerability Scanâ): This is the critical stage.- We execute
trivy imageâŚas a shell command. -
âexit-code 1: This tells Trivy to exit with a status code of 1 if any vulnerabilities are found. This non-zero exit code will cause the Jenkinsshstep to fail, thereby failing the pipeline stage. -
âseverity HIGH,CRITICAL: We are instructing Trivy to only trigger the non-zero exit code for vulnerabilities classified asHIGHorCRITICAL. You can adjust this to includeMEDIUMorLOWas per your security policy.
- We execute
-
stage(âGenerate and Archive Reportâ): This stage is for record-keeping.- We run the scan again, but this time we format the output as JSON (
âformat json) and save it to a file. - The
|| trueis important here. It ensures that this shell command succeeds even if Trivy finds vulnerabilities and exits with code 1. This allows us to archive the report even if the previous scan stage failed the build. -
archiveArtifacts: This Jenkins step saves thescan-report.jsonfile with the build record, making it available for download and review from the Jenkins UI.
- We run the scan again, but this time we format the output as JSON (
-
post { always { ⌠} }: Thepostblock runs after all stages are complete. Thealwayscondition ensures that we clean up the Docker image from the agent regardless of whether the pipeline succeeded or failed.
Common Pitfalls
1. Docker Command Fails with âPermission Deniedâ
A frequent issue is that the Jenkins user does not have permission to interact with the Docker daemon. You might see an error like Got permission denied while trying to connect to the Docker daemon socket. This happens because, by default, only the root user and users in the docker group can access the Docker daemon socket.
Solution: You need to add the jenkins user to the docker group on the agent machine. After adding the user to the group, you must restart the Jenkins agent process (or the entire machine) for the new group membership to take effect.
2. Pipeline Fails on Base Image Vulnerabilities
Sometimes, your scan will detect vulnerabilities in the official base image you are using (e.g., python:3.9-slim, node:18-alpine). Often, these vulnerabilities have not yet been patched by the base image maintainers. Continuously failing your build for issues you cannot fix is counterproductive.
Solution: Trivy allows you to ignore specific vulnerabilities. You can create a file named .trivyignore in your project repository and list the CVE IDs you wish to suppress, along with a reason or expiry date. You can then reference this file in your scan command using the âignorefile flag: trivy image âignorefile .trivyignore ⌠This practice ensures you are making a conscious decision to accept a risk, rather than letting it block your development pipeline indefinitely.
Conclusion
By integrating Trivy into your Jenkins pipeline, you have built a powerful, automated guardrail for your containerized applications. This setup provides immediate feedback on security vulnerabilities, empowering developers to address issues long before they reach production. Automating security scanning not only strengthens your applicationâs security posture but also embeds a culture of security-consciousness within your development team. From here, you can expand this pipeline to push reports to a centralized security dashboard, send notifications on critical findings, or even enforce stricter policies based on vulnerability scores.
đ Read the original article on TechResolve.blog
â Support my work
If this article helped you, you can buy me a coffee:

Top comments (0)