CI Integration
Scout CI Integration
A scanner that doesn't fail the build is just a dashboard. Wiring Scout into CI as a gate is what turns reactive scanning into something that actually keeps vulnerable images out of production.
The Scout GitHub Action
Open catalog-service-node/.github/workflows/pipeline-docker-cloud.yaml to see how Scout integrates into a real pipeline.
The key gate step:
- name: Docker Scout CVEs
uses: docker/scout-action@v1
with:
command: cves
image: ${{ steps.build.outputs.imageid }}
only-severities: critical,high
exit-code: true
Two flags do the heavy lifting:
only-severities: critical,high— only fail on what actually matters; medium and low don't block the pipelineexit-code: true— makes the action fail the build when matching CVEs are found
That's the gate. If a critical or high CVE shows up, the PR can't merge and the image can't deploy.
A more complete pipeline
A typical Scout-in-CI pipeline does several things in sequence:
# 1. Build with SBOM and provenance attached
- name: Build image
id: build
uses: docker/build-push-action@v5
with:
tags: ${{ env.IMAGE_NAME }}
sbom: true
provenance: mode=max
load: true
# 2. Quickview — surfaces a summary in the action log
- name: Docker Scout quickview
uses: docker/scout-action@v1
with:
command: quickview
image: ${{ steps.build.outputs.imageid }}
# 3. Compare against the previous prod image
- name: Docker Scout compare
uses: docker/scout-action@v1
with:
command: compare
image: ${{ steps.build.outputs.imageid }}
to: registry.example.com/catalog-service:prod
ignore-unchanged: true
# 4. Hard gate on critical/high
- name: Docker Scout CVE gate
uses: docker/scout-action@v1
with:
command: cves
image: ${{ steps.build.outputs.imageid }}
only-severities: critical,high
exit-code: true
# 5. Policy gate
- name: Docker Scout policy gate
uses: docker/scout-action@v1
with:
command: policy
image: ${{ steps.build.outputs.imageid }}
exit-code: true
The order matters: quickview and compare run before the gate, so the developer sees what's wrong even when the gate fails. Nothing is more frustrating than a CI that says "FAILED" with no detail.
Tuning the gate
A real-world gate has to balance security and developer flow. A few patterns that work well:
| Pattern | What it does |
|---|---|
only-severities: critical,high |
Only block on CVEs that meaningfully matter |
only-fixed: true |
Only block on CVEs where a fix is actually available |
ignore-unchanged: true |
Don't re-flag CVEs that were already in the previous image |
Block on policy not raw cves |
Use organisational policy rather than every CVE everywhere |
Local pre-flight check
Developers can run the same gate locally before pushing — fewer broken builds:
docker scout cves catalog-service:slim \
--only-severity critical,high \
--org <YOUR_ORG> \
--exit-code
Exit code is non-zero if anything matches. Wire this into a pre-commit hook or a make security target.
Continue to Recommendations & Comparisons, or jump to the pro-active half of the workshop: Migrating to DHI.