Chapter 29: Scan Pipeline in Jenkins
Chala mitrano, aaj aapan badge pipeline madhe scans: SonarQube, Trivy, Dependency-Check, ZAP, Semgrep, Gitleaks, Checkov, Syft, Cosign chi kalpana. Key paste nako. Ghabru naka.
What you will learn in this chapter
- One command per scan and failure shape
- Combined Jenkinsfile that stops before lab Live
- Cosign as concept with no keys
- Conveyor picture with scan stages in the middle
Concepts in this chapter
- 29.1Scans are gates, not decorations
- 29.2SonarQube quality gate
- 29.3Trivy
- 29.4OWASP Dependency-Check
- 29.5ZAP baseline
- 29.6Semgrep
- 29.7Gitleaks
- 29.8Checkov
- 29.9Syft SBOM
- 29.10Cosign, as a concept, with no keys
- 29.11One combined pipeline
The chapter recap is at the end of the last concept page.
Practice Tasks
Suppose we are on the DevOps team at Infosys, the IT services company, working from Pune. Sneha Kulkarni leads the team, and we look after the client billing portal. Costs are counted in INR. In the tasks below we do real DevOps jobs on this project using what this lesson teaches. Infosys is a real company, but this project, the people, servers, IP addresses and numbers are made up for practice.
0 / 12
Easy Declarative Jenkinsfile: build and test
Why: Pipeline as code lives in Git with the app, so every change is reviewed.
What to do: Write a declarative Jenkinsfile: agent any; stage Build runs sh 'mvn -B package'; stage Test runs sh 'mvn test'.
- Start with pipeline { and close it with } at the end.
- Add agent, then stages { } with one stage('Name') { steps { } } per step.
- Put the commands inside steps using sh '...'.
- Count your { and } so every block is closed, then click Check answer.
Easy Static site image
Why: Shipping the built site inside nginx gives one artefact to deploy.
What to do: Write a Dockerfile: FROM nginx:1.27-alpine, copy the folder dist/ into /usr/share/nginx/html/, and expose 80.
- Start with FROM and the base image.
- Set WORKDIR, then COPY files and RUN install steps, one instruction per line.
- Add ENV, EXPOSE or USER lines if the task asks.
- End with CMD (or ENTRYPOINT) and click Check answer.
Easy Build an image
Why: Building from a Dockerfile gives the same image on every machine.
What to do: Build an image from the Dockerfile in the current folder and tag it infosys/client-billing:1.2.3.
- Read the task and pick the tool it needs (git, docker, kubectl, terraform, ansible...).
- Write the tool name, then the sub-command (the action word).
- Add the flags the task needs, each followed by its value.
- Add names, files or paths at the end, then click Check answer.
Easy List local images
Why: You must know what images take space on the build server.
What to do: List the images on this machine.
- Read the task and pick the tool it needs (git, docker, kubectl, terraform, ansible...).
- Write the tool name, then the sub-command (the action word).
- Add the flags the task needs, each followed by its value.
- Add names, files or paths at the end, then click Check answer.
Medium Run the container as a non-root user
Why: If the app is hacked, a non-root user limits the damage.
What to do: Write a Dockerfile: FROM node:20-alpine, WORKDIR /app, COPY . ., RUN npm ci --omit=dev, then switch to the existing user node, and CMD ["node","index.js"].
- Start with FROM and the base image.
- Set WORKDIR, then COPY files and RUN install steps, one instruction per line.
- Add ENV, EXPOSE or USER lines if the task asks.
- End with CMD (or ENTRYPOINT) and click Check answer.
Medium Run the build inside a Docker agent
Why: A Docker agent gives a clean, versioned toolchain for every build.
What to do: Declarative pipeline with agent docker { image 'maven:3.9-eclipse-temurin-21' } and stage Build running sh 'mvn -B verify'.
- Start with pipeline { and close it with } at the end.
- Add agent, then stages { } with one stage('Name') { steps { } } per step.
- Put the commands inside steps using sh '...'.
- Count your { and } so every block is closed, then click Check answer.
Medium Build from another Dockerfile
Why: Teams keep separate Dockerfiles for dev and prod.
What to do: Build using docker/Dockerfile.prod with the current folder as context, tagged infosys/client-billing:prod.
- Read the task and pick the tool it needs (git, docker, kubectl, terraform, ansible...).
- Write the tool name, then the sub-command (the action word).
- Add the flags the task needs, each followed by its value.
- Add names, files or paths at the end, then click Check answer.
Hard Use Jenkins credentials safely
Why: withCredentials masks the password and removes it after the block.
What to do: Inside stage Push steps, use withCredentials with usernamePassword(credentialsId: 'reg-cred', usernameVariable: 'U', passwordVariable: 'P') and run sh 'echo $P | docker login -u $U --password-stdin registry.infosys.example.com'. Wrap it in a full declarative pipeline with agent any.
- Start with pipeline { and close it with } at the end.
- Add agent, then stages { } with one stage('Name') { steps { } } per step.
- Put the commands inside steps using sh '...'.
- Count your { and } so every block is closed, then click Check answer.
Hard Parallel test stages
Why: Running unit and lint at the same time halves feedback time.
What to do: Declarative pipeline, agent any, stage Checks containing parallel with stage Unit (sh 'npm test') and stage Lint (sh 'npm run lint').
- Start with pipeline { and close it with } at the end.
- Add agent, then stages { } with one stage('Name') { steps { } } per step.
- Put the commands inside steps using sh '...'.
- Count your { and } so every block is closed, then click Check answer.
Hard Build argument for the version
Why: One Dockerfile can build any version when the version is an ARG.
What to do: Write a Dockerfile: ARG NODE_VERSION=20 before FROM, then FROM node:${NODE_VERSION}-alpine, then LABEL maintainer="sneha@infosys.example.com".
- Start with FROM and the base image.
- Set WORKDIR, then COPY files and RUN install steps, one instruction per line.
- Add ENV, EXPOSE or USER lines if the task asks.
- End with CMD (or ENTRYPOINT) and click Check answer.
Hard Add a HEALTHCHECK
Why: Docker and orchestrators restart containers that stop answering.
What to do: Write a Dockerfile: FROM infosys/client-billing:1.2.3, then a HEALTHCHECK every 30s with timeout 3s that runs curl -f http://localhost:8080/health || exit 1.
- Start with FROM and the base image.
- Set WORKDIR, then COPY files and RUN install steps, one instruction per line.
- Add ENV, EXPOSE or USER lines if the task asks.
- End with CMD (or ENTRYPOINT) and click Check answer.
Hard Multi-stage Go build
Why: The final image carries only the binary, so it is small and has fewer CVEs.
What to do: Write a two-stage Dockerfile. Stage "build": FROM golang:1.22 AS build, WORKDIR /src, COPY . ., RUN CGO_ENABLED=0 go build -o /out/client-billing . Stage 2: FROM gcr.io/distroless/static, COPY --from=build /out/client-billing /client-billing, USER nonroot, ENTRYPOINT ["/client-billing"].
- Start with FROM and the base image.
- Set WORKDIR, then COPY files and RUN install steps, one instruction per line.
- Add ENV, EXPOSE or USER lines if the task asks.
- End with CMD (or ENTRYPOINT) and click Check answer.
Ravi Sir's Cards: 25 revision, interview and comparison cards for this chapter · मराठी cards