容器镜像安全是DevOps实践里容易被忽视的环节。镜像构建时引入的漏洞会随着镜像分发到每一台运行主机,等到生产环境被攻击才发现问题,整改成本远高于构建阶段。镜像安全扫描的核心是把漏洞检测前置到CI/CD流水线:构建完成后扫描、出问题就阻断发布。Trivy是目前使用最广的开源镜像扫描器,覆盖容器镜像、文件系统、Git仓库和Kubernetes清单,不依赖数据库即可对常见漏洞完成比对,适合直接嵌入流水线。
Trivy漏洞扫描原理与安装配置
Trivy通过解析镜像层的软件包清单(dpkg、rpm、apk等包管理器数据库),把包名和版本号与漏洞数据库比对,得出受影响列表。它支持CVE、GHSA、Red Hat CVE等多个数据源,离线部署时可用trivy db update下载漏洞库后镜像内网使用。
# 安装Trivy(Rocky/Ubuntu均支持)
sudo apt install -y wget apt-transport-https gnupg
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor | sudo tee /usr/share/keyrings/trivy.gpg
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb generic main" | sudo tee /etc/apt/sources.list.d/trivy.list
sudo apt update && sudo apt install -y trivy
# 扫描镜像
trivy image --severity HIGH,CRITICAL --no-progress nginx:1.25
输出会列出每个漏洞的库名、当前版本、修复版本和风险等级。实际使用中关注两类:一是CRITICAL/HIGH等级的漏洞,优先处理;二是存在修复版本但基础镜像不更新导致长期滞留的漏洞,这类要靠基础镜像升级策略解决。
镜像漏洞扫描结果解读与误报处理
Trivy扫描结果的几类常见情况:操作系统层漏洞(glibc、openssl等)通常由基础镜像引入,处理方式是重建基础镜像或升级基础镜像版本;应用层依赖漏洞(Python pip包、Node npm包)需要更新依赖版本后重新构建;部分漏洞标注”受影响版本”但实际代码路径未被使用,属于理论风险,需要结合业务判断是否必须立即修复。
# 生成JSON格式结果,便于自动化处理
trivy -f json -o scan-result.json --severity HIGH,CRITICAL nginx:1.25
# 只看可修复项
trivy --ignore-unfixed --severity HIGH,CRITICAL nginx:1.25
–ignore-unfixed只列出有修复版本的漏洞,把这类漏洞当成必须处理项,没有修复版本的可以单独登记、按风险等级排期,避免把有限人力耗在无解的问题上。
基础镜像选型与供应链安全治理
镜像供应链治理要从基础镜像源头抓起。同一应用用不同基础镜像,漏洞数量可能差出一个数量级。选择基础镜像的优先级:官方镜像优先,其次考虑发行版的精简镜像,再考虑多阶段构建把运行时依赖剥离。alpine镜像体积小,但musl libc与glibc行为差异会导致部分应用出问题,不能只看漏洞数量。
# 多阶段构建:构建阶段与运行阶段分离
FROM golang:1.22 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o app .
FROM gcr.io/distroless/static:nonroot
COPY --from=builder /app/app /app/app
USER nonroot:nonroot
EXPOSE 8080
ENTRYPOINT ["/app/app"]
运行阶段只保留可执行文件和运行所需文件,不保留包管理器、shell和编译工具,攻击面成倍缩小,可扫描的漏洞数量也会显著下降。distroless、scratch这类镜像没有包管理器,Trivy扫描时报告的漏洞主要集中在可执行文件本身。
CI/CD流水线集成:构建即扫描、扫描即阻断
扫描要真正产生约束力,必须嵌入流水线并在漏洞超过阈值时阻断发布。GitHub Actions、GitLab CI、Jenkins都有现成步骤,核心是设置两条规则:CRITICAL级别漏洞数量为0才放行;HIGH级别漏洞超限即告警通知。
# GitLab CI 中的镜像安全扫描示例
stages:
- build
- scan
build:
stage: build
script:
- docker build -t registry.example.com/app:$CI_COMMIT_SHA .
- docker push registry.example.com/app:$CI_COMMIT_SHA
scan:
stage: scan
script:
- trivy -f json -o scan.json --severity HIGH,CRITICAL registry.example.com/app:$CI_COMMIT_SHA
- python -c "
import json,sys
data=json.load(open('scan.json'))
crit=[r for r in data['Results'][0].get('Vulnerabilities',[]) if r['Severity']=='CRITICAL']
if crit:
print('阻断:存在CRITICAL漏洞',len(crit),'个')
sys.exit(1)
print('扫描通过')
"
only:
- main
流水线里还要记录镜像的SBOM(软件物料清单)。Trivy支持生成SBOM,格式兼容SPDX和CycloneDX,把每个镜像的依赖清单归档,出安全事件时可以快速定位哪些运行环境受影响。
运行时镜像安全策略与定期复扫
CI流水线扫描只覆盖构建时刻,镜像仓库里长期不动的老镜像会积累新披露的漏洞。需要定期复扫:镜像仓库策略只保留最近N个tag;每周对生产镜像重新扫描一次,把新暴露的CVE整理成升级计划;更新基础镜像后触发一次全量重扫,验证基础镜像升级是否真的覆盖了历史漏洞。
# 定时复扫仓库内全部镜像
crontab -e
0 3 * * 1 trivy -f json -o /data/scan-weekly.json --severity HIGH,CRITICAL registry.example.com/library --update-all
# 保留策略:删除90天前且非生产tag的镜像
docker image prune -a --filter "until=2160h" --filter "label!=keep"
镜像安全的完整闭环:构建前扫描依赖清单、构建时多阶段裁剪、发布前Trivy阻断、仓库定期复扫、运行时容器只读文件系统。五层都做到位,镜像供应链的风险基本可控制在可接受范围。扫描工具代替不了流程,把阻断策略落进流水线,才是镜像安全从”可做”到”落地”的分界线。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/rong-qi-jing-xiang-an-quan-sao-miao-shi-zhan-trivy-lou-dong/