Integrating Trivy Image Security Scanning into GitLab CI/CD Pipelines
This tutorial demonstrates how to set up automated Docker image vulnerability scanning with Trivy, embed the scan into GitLab CI/CD pipelines, handle severity thresholds, schedule recurring scans, and remediate findings by adjusting the Dockerfile, providing a practical DevOps security workflow.
Image security scanning has become increasingly popular as a way to analyze Docker images against CVE databases and identify vulnerabilities before they reach production.
Several tools can perform such scans, including Trivy, Anchore, Clair, Docker Trusted Registry, and cloud provider services; this guide focuses on using Trivy within a GitLab CI/CD pipeline.
Trivy Overview
Trivy is a simple yet accurate image scanner. Install it with:
$ curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/master/contrib/install.sh | sh -s --b /usr/local/bin
$ sudo mv ./bin/trivy /usr/local/bin/trivy
$ trivy --versionScan an image with:
$ trivy image nginx:alpineTo illustrate the integration, a minimal Dockerfile is used:
FROM debian:buster
RUN apt-get update && apt-get install nginx -yThe image can be built locally with:
$ docker build -t security_scan_example:latest .GitLab CI Configuration
The pipeline includes a build job that builds and pushes the image, and a security_scan job that runs Trivy:
build:
stage: build
image: docker:stable
services:
- docker:dind
tags:
- docker
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
script:
- docker build -t $CI_REGISTRY_IMAGE:latest .
- docker push $CI_REGISTRY_IMAGE:latest
except:
variables:
- $SCHEDULED_PIPELINE
security_scan:
stage: test
image:
name: aquasec/trivy:latest
entrypoint: [""]
services:
- docker:dind
tags:
- docker
script:
- trivy --no-progress --output scanning-report.txt $CI_REGISTRY_IMAGE:latest
artifacts:
reports:
container_scanning: scanning-report.txtThe scan job produces a report that can be downloaded from the pipeline artifacts, showing counts of low, medium, high, and critical vulnerabilities.
To make the pipeline fail on critical issues, Trivy’s --severity CRITICAL and --exit-code 1 options are added, causing the job to exit with a non‑zero status when such vulnerabilities are found.
Scheduled Scans
A nightly scheduled pipeline is added (e.g., at 2 AM) that runs only the security scan job, using a variable SCHEDULED_PIPELINE to differentiate it from the regular build pipeline. The configuration uses a job template to avoid duplication.
.scanning-template: &scanning-template
stage: test
image:
name: aquasec/trivy:latest
entrypoint: [""]
services:
- docker:dind
tags:
- docker
script:
- trivy --no-progress --output scanning-report.json $CI_REGISTRY_IMAGE:latest
- trivy --exit-code 1 --no-progress --severity CRITICAL $CI_REGISTRY_IMAGE:latest
artifacts:
reports:
container_scanning: scanning-report.json
security_scan:
<<: *scanning-template
except:
variables:
- $SCHEDULED_PIPELINE
security_scan:on-schedule:
<<: *scanning-template
only:
variables:
- $SCHEDULED_PIPELINE == "security_scan"When vulnerabilities are found, they can be addressed by updating the base image or removing unnecessary components. The tutorial shows switching the base image to Alpine:
FROM alpine:3.12
RUN apk update && apk add nginx -yAfter rebuilding, the pipeline reports zero vulnerabilities.
Conclusion
The guide demonstrates a straightforward method to embed container image security scanning into GitLab CI/CD using Trivy, handling severity thresholds, scheduling recurring scans, and mitigating findings, providing a practical DevOps security workflow.
DevOps Cloud Academy
Exploring industry DevOps practices and technical expertise.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.