Keep CI scans fast by caching the advisory database, scanning each image digest once, shrinking the image, running the blocking check on changed images only, and moving deep analysis to a scheduled job. A scan developers wait on for ten minutes will eventually be skipped.
Where the time goes
A container scan has four costs: fetching the image, unpacking layers, loading advisory data and matching. Fetching and database download are often the largest. Matching a package list is cheap. Optimize in that order.
Practical steps
- Cache the vulnerability database between runs. Re-downloading it per job wastes minutes. Refresh it on a schedule, not per commit.
- Scan before push from a local archive or layout, so you skip a registry round trip. See scanning without a daemon.
- Scan each digest once. If the image bytes did not change, reuse the earlier result and only refresh the advisory data.
- Make images smaller. Fewer layers and fewer packages mean less to unpack and fewer findings. Multi-stage builds help.
- Scan only what changed. In a monorepo, build and scan the services touched by the commit.
- Run scans in parallel with tests, not after them.
- Give the job enough CPU and disk. Unpacking is disk heavy.
Split blocking from deep
| Check | Where | Blocks merge? |
|---|---|---|
| Known critical, fixable, exploited | CI, every build | Yes |
| Full severity range, license, secrets | CI, on release branch | Policy dependent |
| Deep rescan of all deployed images | Scheduled job | No, alerts only |
Keeping the blocking rule narrow keeps it fast and trusted. A wide rule produces failures developers cannot act on, and they will route around it.
A quick example of the arithmetic
Suppose a scan spends most of its time downloading the advisory database and pulling the image. Caching the database removes one cost. Scanning from a local archive removes the other. The matching step, the part you actually care about, may take only seconds. Look at a timing breakdown of your own job before tuning, because the slow step is often not the one people expect.
Measure it
Record scan duration in your pipeline metrics. Set a target, for example under two minutes for the blocking check, and treat a regression like any other performance bug. If the scan is slow because the image is huge, that is useful feedback about the image.
Try it yourself
Click through it at your own pace, or open it full screen.
Watch how a gate reports a result inside the pull request, which is what a fast scan makes possible.
Quick check
Can I skip the scan for unchanged images?
You can reuse the image analysis by digest but still refresh the advisory match, because the data changes.
Is failing the build on every high finding sensible?
Rarely at first. Start with fixable, exploited findings and widen as the backlog shrinks.
Safeguard offers a CLI and CI integration for dependency and SBOM scanning with policies and gates, and a free scan to try first.
Last reviewed: 19 October 2026.