news 2026/7/8 5:18:46

容器镜像漏洞扫描拖垮 CI:我把构建时间从 20 分钟压回 3 分钟的排查实录

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
容器镜像漏洞扫描拖垮 CI:我把构建时间从 20 分钟压回 3 分钟的排查实录

容器镜像漏洞扫描拖垮 CI:我把构建时间从 20 分钟压回 3 分钟的排查实录

上周三下午,我正准备把一个新功能合并到主分支,CI 突然跑了一个多小时还没结束。平时 3 分钟的构建,硬生生拖到了 20 分钟。翻了一圈日志,罪魁祸首是两周前接入的容器镜像漏洞扫描。

说实话,安全团队的初衷是好的。但把扫描直接塞进构建流程,没做任何优化,这跟在高速公路入口设检查站检查每辆车的底盘没啥区别——堵是必然的。

问题是怎么发现的

事情要从安全合规说起。公司安全团队要求所有上线镜像必须通过漏洞扫描,Severity High 及以上必须清零。我花了一个下午把 Trivy 接进了 GitLab CI,配置看起来挺简单:

scan_image:stage:testimage:aquasec/trivy:latestscript:-trivy image--exit-code 1--severity HIGH,CRITICAL $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

第一遍跑通了,我还挺得意。但接下来的几天,每次推送代码都要等 20 分钟。更离谱的是,开发人员开始抱怨本地分支的 CI 也慢了,因为 merge request 触发的 pipeline 同样要跑完整扫描。

我拉了一下构建耗时数据,扫描阶段占了整个 pipeline 的 78%。Trivy 每次都要重新下载漏洞数据库,然后对镜像逐层扫描。我们的镜像基于一个 Ubuntu 基础镜像,一层叠一层,Trivy 把每一层都拆开来分析。再加上没有缓存,每次都是从零开始。

划重点:漏洞扫描不是不能慢,但慢在构建流程里就是致命伤。

排查时间线

我按时间线记录了整个排查过程,方便后续复盘。

T+0 分钟:确认瓶颈

先看了 GitLab CI 的 stage 耗时。build 阶段 2 分 30 秒,scan 阶段 17 分钟。问题明确:扫描是瓶颈。

# 快速查看各 stage 耗时gl-ci-trace|grep-E"(build|scan|test)"|awk'{print $1, $NF}'

T+5 分钟:分析 Trivy 扫描日志

Trivy 的日志里反复出现Downloading DB...Analyzing layer...。我注意到漏洞数据库下载占了 4 分钟,镜像分析占了 13 分钟。

# 本地复现,加上时间戳timetrivy image--severityHIGH,CRITICAL my-app:latest

本地跑了一遍,结果一样:数据库下载慢,镜像分析慢。

T+15 分钟:定位两个根因

第一个根因:Trivy 默认从 GitHub 下载漏洞数据库,网络不稳定时经常超时重试。第二个根因:我们镜像层数太多,而且有很多重复文件,Trivy 的逐层分析策略在这种情况下效率极低。

T+25 分钟:制定三层修复方案

我画了一个简单的决策树:要么让扫描变快,要么把扫描从构建流程里挪出去,或者两者都做。最后决定三层一起上:缓存漏洞数据库、并行扫描、分层扫描策略。

解决方案:三层修复

第一层:缓存漏洞数据库

Trivy 的漏洞数据库可以缓存到本地或者 registry。我在 CI 里加了一个缓存 job,每天只更新一次数据库,其他 job 直接使用缓存。

.trivy_cache:cache:key:trivy-db-${CI_COMMIT_REF_SLUG}paths:-.cache/trivybefore_script:-mkdir-p .cache/trivy-export TRIVY_CACHE_DIR=.cache/trivy-|if [ ! -f .cache/trivy/db/trivy.db ]; then echo "Cache miss, downloading DB..." trivy image --download-db-only else echo "DB cache hit, skipping download" fi

这一步把数据库下载时间从 4 分钟压到了 10 秒。

第二层:并行扫描 + 分层策略

原来我们扫描的是最终构建完成的镜像。但实际上,很多漏洞来自基础镜像,业务代码层很少有高危漏洞。我改成了先扫描基础镜像,再扫描业务层,两者并行。

scan_base_image:stage:testimage:aquasec/trivy:latestscript:-trivy image--severity HIGH,CRITICAL--skip-dirs /app ubuntu:22.04allow_failure:truescan_app_layer:stage:testimage:aquasec/trivy:latestscript:-trivy filesystem--severity HIGH,CRITICAL /apponly:-merge_requests

filesystem模式扫描的是构建上下文,而不是完整镜像。对于业务代码变更,这通常就够了。只有基础镜像升级时,才触发完整镜像扫描。

第三层:优化镜像本身

扫描慢还有一个原因:镜像太大了。我花了一个小时把镜像从 Ubuntu 换成了 distroless,又砍掉了一些不必要的构建依赖。

# 优化前:Ubuntu 基础镜像,层数多 FROM ubuntu:22.04 RUN apt-get update && apt-get install -y python3 python3-pip COPY requirements.txt . RUN pip install -r requirements.txt COPY . /app # 优化后:多阶段构建 + distroless FROM python:3.11-slim as builder COPY requirements.txt . RUN pip install --user -r requirements.txt FROM gcr.io/distroless/python3 COPY --from=builder /root/.local /home/nonroot/.local COPY --chown=nonroot:nonroot . /app WORKDIR /app ENV PATH=/home/nonroot/.local/bin:$PATH

镜像从 1.2GB 压到了 180MB。镜像小了,Trivy 扫描自然也少了。

踩坑记录

坑 1:Trivy cache 目录权限

GitLab runner 的 cache 目录默认权限是 root,但 Trivy 容器里跑的是非 root 用户。结果缓存写进去了,Trivy 读不出来。解决方式是统一用root用户跑 Trivy,或者调整 cache 目录权限。

scan_image:image:name:aquasec/trivy:latestentrypoint:[""]script:-trivy image--cache-dir /tmp/trivy-cache...

坑 2:–skip-dirs 不生效

我一开始用--skip-dirs /app想跳过业务代码目录,结果发现 Trivy 的image模式里--skip-dirs只对filesystem模式有效。换成filesystem扫描构建上下文,才真正跳过不需要的目录。

坑 3:并行扫描的依赖顺序

scan_base_imagescan_app_layer放在同一个 stage,但scan_app_layer其实依赖 build 阶段的产物。我一开始把它们放错了 stage,导致scan_app_layer跑的时候构建产物还没生成。调整 stage 顺序后解决。

坑 4:distroless 的调试困难

distrioless 镜像里没有 shell,调试起来很费劲。我最后保留了一个debug版本的 Dockerfile,本地调试用debug标签,线上用distroless标签。

# 本地调试dockerbuild-tmy-app:debug-fDockerfile.debug.# 线上部署dockerbuild-tmy-app:latest-fDockerfile.

最终效果

三层修复下来,CI 构建时间从 20 分钟压回了 3 分钟,甚至更短。

优化项优化前优化后节省
漏洞数据库下载4 分钟10 秒~3.8 分钟
镜像扫描13 分钟45 秒~12 分钟
镜像构建3 分钟2 分钟1 分钟
总计20 分钟3 分钟17 分钟

更重要的是,开发人员不再抱怨 CI 慢了。安全合规和开发效率这两件事,终于可以和平共处了。

写在最后

这件事给我最大的教训是:安全工具接入不能简单粗暴。直接把 Trivy 塞进构建流程,不考虑缓存、不考虑分层、不考虑镜像体积,结果就是开发效率和安全合规两边都不讨好。

如果你是安全团队,建议把扫描放在独立的 stage,并且给开发团队留足缓存策略。如果你是开发团队,接入扫描工具的时候,先本地跑一遍time trivy image,看看瓶颈到底在哪。

说到底,DevSecOps 不是把安全工具堆进 CI 就完事了。安全左移没问题,但左移不等于把负担全扔给开发。找到一个让两边都能接受的方案,才是真正的工程实践。

如果你也在 CI 里踩过扫描的坑,欢迎评论区交流。踩坑的路上,你并不孤单。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/8 5:16:04

5分钟掌握Luyten:Java反编译工具的最佳图形化解决方案

5分钟掌握Luyten:Java反编译工具的最佳图形化解决方案 【免费下载链接】Luyten An Open Source Java Decompiler Gui for Procyon 项目地址: https://gitcode.com/gh_mirrors/lu/Luyten 你是否曾经遇到过需要分析Java字节码文件却无从下手的困境?…

作者头像 李华
网站建设 2026/7/8 5:16:04

vsftpd 虚拟用户 vs 本地用户:3种登录模式权限与安全深度对比

Vsftpd 虚拟用户与本地用户:权限控制与安全配置深度解析在企业级文件传输服务部署中,Vsftpd作为Linux平台最主流的FTP服务解决方案,其三种用户认证模式的选择直接影响系统安全性和管理效率。本文将深入对比匿名用户、本地系统用户和虚拟用户三…

作者头像 李华
网站建设 2026/7/8 5:15:12

抖音批量下载完全指南:三步掌握免费无水印视频保存方法

抖音批量下载完全指南:三步掌握免费无水印视频保存方法 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback supp…

作者头像 李华
网站建设 2026/7/8 5:14:10

软件测评实验室认可,作业指导书文件清单分享

作业指导书是规范人员操作流程的标准化操作指南,作业指导书文件需要满足可操作性强、步骤清晰、目标明确等特点。实验室借助作业指导书可以保证过程一致性、保证输出质量、提高检测效率、降低沟通成本、便于知识沉淀和管理。一、作业指导书建议包含的11个要素&#…

作者头像 李华