导读:本期聚焦于新井创作的《如何将镜像扫描接入CI流水线实现自动化安全检测?》,敬请观看详情。容器化应用上线前,镜像里潜藏的漏洞、恶意依赖和不安全配置往往难以靠人工排查。把镜像扫描接入CI流水线,可以让每次构建都自动完成安全体检,在问题进入生产环境之前就被拦截。本文从容器镜像的安全风险说起,介绍Trivy、Grype等主流扫描工具的特点与选型思路,详细演示在GitLab CI与Jenkins中配置扫描任务的完整流程,并讲解如何设置漏洞白名单、阻断阈值与扫描结果报告,让安全检查既不拖慢发布节奏,又能守住安全底线。

容器镜像是云原生应用交付的基本单元,一个镜像从构建到运行,往往要经历开发、测试、生产多个环节。如果镜像本身携带已知漏洞的依赖包、过时的系统组件或者不安全的配置,那么这些风险就会随着镜像的分发被复制到每一个运行实例上。将镜像扫描接入CI流水线,是当前容器安全建设中性价比最高的实践之一:它把安全检查前置到构建阶段,让每一次代码提交都能得到自动化的安全体检,问题在进入镜像仓库之前就被发现和修复。

为什么需要在CI阶段做镜像扫描

传统的安全检测通常安排在上线前,由安全团队对即将发布的应用进行一次性的渗透测试或漏洞评估。这种方式在容器时代显得力不从心,原因在于容器镜像的更新频率极高,一个团队一天可能产出几十甚至上百个镜像版本,人工逐一检查既不现实也不经济。而镜像的构成又非常复杂,一个基于Debian或Alpine的基础镜像,加上应用依赖的npm包、Python包、JAR包,任何一个环节都可能引入已知漏洞。

把扫描动作放到CI流水线中,核心价值在于“左移”。开发者在提交代码后几分钟内就能收到漏洞报告,此时修复成本最低——他刚刚写过这段代码,对依赖关系了如指掌,升级一个有漏洞的依赖包可能只需要几分钟。如果同样的问题留到上线后被安全团队发现,就需要重新走一轮开发、测试、发布的完整流程,修复成本成倍增加。

此外,CI阶段的扫描还有一个隐性好处:它可以作为质量门禁。当镜像中存在高危漏洞时直接让流水线失败,阻止问题镜像推送到仓库,从机制上杜绝“带病上线”。这比事后发通知、催修复要可靠得多。

主流镜像扫描工具选型

目前社区活跃度最高、集成体验较好的扫描工具主要有Trivy和Grype两款,此外还有Clair、Docker Scout等方案。选型时需要综合考虑扫描速度、漏洞库覆盖度、CI集成难度和离线场景支持。

Trivy是Aqua Security开源的扫描器,支持扫描镜像文件系统、IaC配置、密钥泄露等多种目标,漏洞库更新及时,单次扫描通常在几十秒内完成。它提供单二进制发行版,没有外部依赖,在CI环境中安装非常方便,同时内置了--exit-code--severity参数,天然适合做流水线门禁。

Grype来自Anchore团队,特点是漏洞匹配引擎(Grype的匹配规则基于Syft生成的SBOM),对Java、Go等语言生态的依赖识别能力较强,输出格式支持JSON、表格等多种形式。如果团队已经在使用Syft做软件物料清单,Grype是很自然的选择。

Clair是较早的开源方案,采用API服务架构,适合搭建集中式扫描平台,但部署和维护成本较高,对中小团队不够友好。Docker Scout是Docker官方推出的服务,与Docker Hub深度集成,但对自建仓库的支持有限。综合来看,大多数团队从Trivy入手是最稳妥的选择。

在GitLab CI中配置镜像扫描

GitLab CI是目前国内使用广泛的CI系统,它的流水线定义在.gitlab-ci.yml文件中。接入扫描的基本思路是:在镜像构建任务之后增加一个扫描任务,扫描本地构建产物或已推送的镜像,根据扫描结果决定流水线是否通过。

stages:
  - build
  - scan

build_image:
  stage: build
  image: docker:24
  services:
    - docker:24-dind
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA .
    # 先推送到仓库,供扫描任务拉取
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA

scan_image:
  stage: scan
  image:
    name: aquasec/trivy:latest
    entrypoint: [""]
  variables:
    TRIVY_USERNAME: "$CI_REGISTRY_USER"
    TRIVY_PASSWORD: "$CI_REGISTRY_PASSWORD"
  script:
    # 只统计高危和严重级别漏洞,存在则返回退出码1
    - trivy image --exit-code 1 --severity HIGH,CRITICAL
      --ignore-unfixed $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
  cache:
    paths:
      - .cache/trivy

这个配置中有几个细节值得注意。第一,扫描任务使用了官方Trivy镜像并清空了entrypoint,这样才能直接执行自己的命令。第二,--ignore-unfixed参数会过滤掉上游尚未发布修复版本的漏洞,避免流水线被无法解决的问题卡死。第三,通过cache缓存漏洞数据库目录,可以显著减少每次任务下载数据库的时间,Trivy的漏洞库有上百MB,缓存之后扫描任务通常能缩短一到两分钟。

如果希望扫描结果可追溯,可以在script中追加一行trivy image --format json -o trivy-report.json,再通过artifacts把报告文件归档,团队成员可以在流水线页面直接下载查看完整的漏洞清单。

在Jenkins中配置镜像扫描

对于使用Jenkins的团队,推荐通过声明式流水线(Jenkinsfile)集成扫描。Jenkins的优势在于可以用Groovy脚本灵活控制流程,例如根据漏洞数量做差异化处理。

pipeline {
    agent any
    environment {
        IMAGE = 'registry.ippipp.com/myapp'
        TAG = "${env.BUILD_NUMBER}"
    }
    stages {
        stage('Build') {
            steps {
                sh 'docker build -t ${IMAGE}:${TAG} .'
            }
        }
        stage('Scan') {
            steps {
                // 使用Trivy扫描,输出简要报告
                sh 'trivy image --severity HIGH,CRITICAL ${IMAGE}:${TAG}'
            }
        }
        stage('Gate') {
            steps {
                script {
                    def exitCode = sh(
                        script: 'trivy image --exit-code 1 --severity CRITICAL ${IMAGE}:${TAG}',
                        returnStatus: true
                    )
                    if (exitCode != 0) {
                        unstable('发现严重漏洞,构建标记为不稳定')
                        // 如需硬阻断可改为 error('安全门禁未通过')
                    }
                }
            }
        }
    }
}

上面的写法演示了一种常见的渐进式策略:先用unstable标记构建状态,让团队观察一段时间漏洞分布,再切换为error强制阻断。直接开启硬门禁容易导致所有流水线瞬间红掉,开发抵触情绪强烈,最终策略难以推行。先警告后阻断的分阶段落地方式在实践中被证明更有效。

另外需要注意Jenkins节点上的Trivy安装方式,推荐在节点初始化脚本中固定安装某个版本,而不是每次任务都拉取latest,这样能保证扫描行为的一致性,也便于排查误报问题。

治理策略:白名单、阈值与报告

扫描接入只是第一步,真正决定这套机制能否长期运行的是治理策略。最常见的问题是误报和无法修复的漏洞:某个基础镜像的组件官方已经停止维护,或者漏洞只影响特定运行场景。Trivy提供了.trivyignore文件来处理这类情况,把确认可接受的CVE编号写入文件并提交到代码仓库,配合注释说明豁免原因和有效期,就能实现白名单的版本化管理。

# .trivyignore 示例
# CVE-2023-XXXX: 仅影响Windows场景,容器为Linux环境,豁免至下季度复审
CVE-2023-XXXX
# CVE-2024-YYYY: 基础镜像组件,等待官方补丁
CVE-2024-YYYY

阈值设置也需要分层思考。对于核心业务服务,可以要求CRITICAL级别必须清零;对于内部工具类服务,阈值可以放宽到HIGH。通过为不同项目组维护不同的扫描配置,安全要求的严格程度就能与业务重要性匹配,避免一刀切带来的效率损耗。

最后,扫描结果应该汇聚到统一平台可视化。如果团队规模较大,可以在流水线之外部署Trivy Server模式,各CI节点作为客户端共享漏洞库,减少外网依赖和重复下载;也可以把JSON格式的报告推送到漏洞管理平台,按漏洞维度统计趋势,观察整体安全状况是否随时间改善。定期(例如每周)重新扫描一次镜像仓库中的存量镜像也很重要,因为漏洞库每天都会更新,昨天干净的镜像今天可能就被标记出新漏洞。安全是一个持续的过程,而不是一次性的检查动作。

镜像扫描CI流水线容器安全修改时间:2026-08-31 06:44:33

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。