自动化脚本定期扫描容器镜像安全漏洞实操指南
核心答案
如果你正在管理 Docker 镜像仓库或生产容器环境,定期扫描镜像漏洞是必不可少的安全措施。
本文介绍一套自动化方案:使用 Trivy 作为扫描工具,通过 Shell 脚本结合系统 cron 定时任务,实现每天自动扫描所有本地镜像并生成报告。
无需复杂配置,零基础也能在 10 分钟内完成部署,有效发现高危漏洞并及时处置。
适用场景与准备条件
这套方案适合以下场景:
- 维护 Docker 私有镜像库,需要定期审计所有镜像的安全性。
- 生产环境使用容器编排(如 Kubernetes),希望自动检查基础镜像是否带有已知漏洞。
- 个人或小团队没有商业容器安全平台,但希望用低成本实现基本巡检。
准备条件:
- 一台已安装 Docker 的 Linux 服务器(建议 CentOS 7+ 或 Ubuntu 18.04+)。
- 具备 sudo 权限的用户,能执行 apt/yum 安装操作。
- 了解基本的命令行操作(复制、粘贴、修改路径即可)。
操作步骤:从安装到定时执行
1. 安装 Trivy
Trivy 是目前社区最流行的开源镜像漏洞扫描器,支持 CVE、Docker 镜像、文件系统等多种扫描模式。
# 基于 Ubuntu/Debian
sudo apt-get install wget apt-transport-https gnupg lsb-release
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add -
echo deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list.d/trivy.list
sudo apt-get update && sudo apt-get install trivy -y
# 基于 CentOS/RHEL(使用 rpm)
sudo rpm -ivh https://github.com/aquasecurity/trivy/releases/download/v0.50.1/trivy_0.50.1_Linux-64bit.rpm
安装完成后运行 trivy --version 确认版本。
2. 编写扫描脚本
创建一个用于定期扫描的脚本文件,比如 /opt/scan_images.sh:
#!/bin/bash
# 脚本:每日扫描所有本地 Docker 镜像
REPORT_DIR="/var/log/trivy-reports"
DATE=$(date +%Y%m%d)
mkdir -p $REPORT_DIR
# 获取所有镜像列表(包括标签)
images=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep -v "")
for img in $images; do
echo "扫描镜像: $img"
trivy image --severity CRITICAL,HIGH --quiet --no-progress --format json $img > $REPORT_DIR/${img//\//_}_$DATE.json 2>&1
done
# 可选:清理超过 30 天的旧报告
find $REPORT_DIR -type f -name "*.json" -mtime +30 -delete
echo "扫描完成,报告保存在 $REPORT_DIR"
说明:--severity CRITICAL,HIGH 只关注高危以上漏洞,减少噪音;--format json 方便后续分析。
如需全量扫描可去掉该参数。
赋予执行权限:chmod +x /opt/scan_images.sh。
3. 配置 cron 定时任务
通过 crontab 让脚本每天凌晨 2 点自动运行:
crontab -e
# 在文件末尾添加(每天 2:00 执行)
0 2 * * * /bin/bash /opt/scan_images.sh >> /var/log/trivy-cron.log 2>&1
保存后系统会自动注册定时任务。
可以使用 crontab -l 确认。
避坑指南
- trivy 镜像清单更新:每次扫描 Trivy 会从 GitHub 下载漏洞数据库,如果服务器无法访问外网,需要配置代理或使用离线数据库(参考 Trivy 官方文档)。建议在非高峰时段运行,避免影响业务。
- 镜像名称含特殊符号:脚本中使用
${img//\//_}将斜杠替换为下划线,防止创建文件时因路径分隔符出错。如果你镜像名称中包含冒号,注意文件名可能不合法,可改为其他安全字符。 - 扫描性能影响:一次性扫描本地所有镜像可能占用较多 CPU 和内存,建议分批或只在低负载时段执行。如果镜像数量超过 100 个,可以考虑在脚本中添加
sleep 5暂停间隔。 - 报告分析:生成的是 JSON 格式,直接阅读不太方便。可以额外编写一个汇总脚本,用
jq提取漏洞数量并发送邮件或写入日志。例如:cat report.json | jq '.Results[].Vulnerabilities[] | select(.Severity=="CRITICAL") | .VulnerabilityID'。
效果验证
执行一次测试扫描确认配置正确:
sudo /opt/scan_images.sh
查看报告目录:ls -l /var/log/trivy-reports/ 应看到形如 nginx_latest_20250310.json 的文件。
检查 cron 执行日志:tail -n 20 /var/log/trivy-cron.log,如果没有错误则说明定时任务正常工作。
你也可以临时将 cron 时间改为当前时间后一分钟,验证自动执行效果(记得改回原时间)。
高频问题解答
Q1:Trivy 扫描需要联网吗?
需要首次下载漏洞数据库,后续扫描会增量更新。如果内网环境,可以预先下载离线数据库文件并配置环境变量 TRIVY_DB_REPOSITORY 指向本地路径(参考 trivy help)。
Q2:扫描结果如何通知我?
可以在脚本末尾加入邮件发送命令(如 mail 或 mutt),或集成到企业微信、钉钉、Slack 机器人。最简单的做法是将日志中的高危 CVE 数量写入文件,再用监控工具采集。
Q3:脚本只扫描现存镜像,新拉的镜像怎么办?
脚本每次运行时都会获取本地所有镜像,所以新拉取的镜像会在下一次定时任务中被扫描。如果需要实时扫描,可以结合 Docker 事件监听:docker events --filter event=pull,触发即时扫描。
Q4:如果某镜像扫描失败,如何处理?
可以在脚本中加入错误捕获:if [ $? -ne 0 ]; then echo "镜像 $img 扫描失败" >> $REPORT_DIR/errors.log; fi,方便单独排查。常见失败原因是镜像不存在或 Trivy 版本不兼容,检查 Docker 守护进程是否运行正常。
如果你正在处理自动化扫描容器镜像安全漏洞的落地,建议先按本文步骤在测试服务器上完整执行一遍,再根据你自己的镜像数量和网络环境做微调。
遇到异常时重点检查 Trivy 安装和 cron 路径是否正确。