自动化脚本定期扫描容器镜像安全巡检漏洞
容器镜像安全巡检漏洞,最实用的做法是使用开源的 Trivy 扫描器,配合 Linux 自带的 Crontab 定时任务,写一个简单的 Shell 脚本自动执行扫描并保存报告。
整个过程不需要购买商业产品,一台能跑 Docker 的服务器就能完成。
本文按零基础思路,从准备到验证逐步说明。
先确认环境:装好 Docker 和 Trivy
开始之前,请确认服务器满足两个条件:
- 已安装 Docker,并且当前用户能执行
docker images命令。没有安装的话,可以用curl -fsSL https://get.docker.com | sh快速安装。 - 已安装 Trivy。推荐使用官方二进制包,例如在 x86_64 的 Linux 上执行:
download_url="https://github.com/aquasecurity/trivy/releases/download/v0.49.1/trivy_0.49.1_Linux-64bit.tar.gz"
wget $download_url -O trivy.tar.gz
sudo tar zxvf trivy.tar.gz -C /usr/local/bin trivy
装好后运行 trivy --version,能看到版本号就说明正常。
注意版本号会更新,建议到 Trivy 官方 GitHub Releases 页面查最新版。
写一个可复用的镜像漏洞巡检脚本
创建目录 /opt/scan-sec,并在里面新建脚本 scan_images.sh:
#!/bin/bash
SCAN_DIR="/opt/scan-sec/reports"
DATE=$(date +%Y%m%d%H%M)
mkdir -p "$SCAN_DIR"
# 遍历本机所有带仓库标签的镜像,逐个扫描
for image in $(docker images --format "{{.Repository}}:{{.Tag}}" | grep -v ""); do
echo "[$(date '+%F %T')] 开始扫描: $image"
trivy image --severity HIGH,CRITICAL --ignore-unfixed --format json -o "$SCAN_DIR/${image//\//_}${DATE}.json" "$image"
done
脚本逻辑很简单:
先建报告目录,
再用 docker images 拿到镜像列表,
过滤掉 的悬空镜像,
最后逐个执行 Trivy 扫描。--severity HIGH,CRITICAL 只关注高危和严重漏洞,--ignore-unfixed 跳过没有补丁的漏洞,
减少无效噪音。
给脚本加上执行权限:
chmod +x /opt/scan-sec/scan_images.sh
先手动执行一次,确认没有报错:
/opt/scan-sec/scan_images.sh
扫描过程中会显示进度,结束后到 /opt/scan-sec/reports 目录查看 JSON 报告。
如果本机镜像较多,首次扫描因为要下载漏洞数据库,耗时会长一些,属于正常现象。
用 Crontab 让扫描每周自动跑
编辑 Crontab 配置文件:
crontab -e
添加下面这行,表示每周日凌晨 3 点执行扫描:
0 3 * * 0 /opt/scan-sec/scan_images.sh >> /var/log/trivy-scan.log 2>&1
分号里的五个位置分别对应分钟、小时、日期、月份、星期。
周日写 0 或 7 都可以。
把日志输出到 /var/log/trivy-scan.log,方便后续排查。
保存后可以用这条命令确认定时任务是否注册成功:
crontab -l | grep scan
看到刚才加的内容就说明配置生效了。
以后每次扫描结果都会以 JSON 文件形式存到报告目录,文件名带上日期时间,不会覆盖历史记录。
这些坑最容易踩,提前避开
- Trivy 漏洞数据库下载失败:第一次扫描或数据库过期时需要联网下载,如果服务器无法访问外网,扫描会卡住或报错。建议提前执行
trivy image --download-db-only手动更新一次,或者配置企业代理。 - 磁盘爆满:一个镜像的 JSON 报告可能几十MB,长期累积会占满磁盘。建议在脚本里加一句保留最近 30 天报告的清理命令:
find "$SCAN_DIR" -name "*.json" -mtime +30 -delete
- 镜像名包含特殊字符:镜像名里的
/在生成文件名时会被替换成_,避免目录层级错乱。如果镜像名有空格,脚本需要再调整,通常是先对镜像名做转义。 - Crontab 环境变量问题:Cron 执行时 PATH 很精简,脚本里尽量使用绝对路径,或者像示例那样直接用
trivy命令的绝对路径/usr/local/bin/trivy,否则可能提示找不到命令。
验证自动化扫描是否真的生效
不要等周日才确认,现在先手动模拟一次。
运行下面命令检查脚本有没有语法错误:
bash -n /opt/scan-sec/scan_images.sh
再看日志文件:
tail -f /var/log/trivy-scan.log
如果想提前验证 Crontab 的执行逻辑,可以临时把时间改成下一分钟,比如当前是 10:15,就写 16 10 * * *,观察是否正常触发,测试完再改回原值。
最终检查报告目录:
ls -lh /opt/scan-sec/reports/
只要有新的 JSON 文件生成,并且文件里包含 Vulnerabilities 字段,就说明容器镜像安全巡检漏洞的自动化流程已经跑通了。
后续你可以把 JSON 报告接入告警系统,或者定期用脚本解析高危漏洞并发送通知。
如果你在用云服务器做容器环境,建议把报告目录挂载到独立磁盘或对象存储,避免因服务器重装丢失历史扫描数据。
安全巡检是持续工作,保持固定周期比一次彻底扫描更有价值。
高频问题解答
1. 镜像漏洞扫描一定要装额外工具吗?
不一定,但 Trivy 是目前开源免费里使用最方便的,支持多种镜像格式,无需配置数据库就能开始扫。
对比 docker scan 需要登录 Docker Hub,Trivy 更适合内网和自动化脚本。
2. 扫描结果怎么主动通知我?
扫描脚本里可以对接钉钉、企业微信或邮件。
核心思路是在 Trivy 输出 JSON 后,用 Python 或 jq 提取高危漏洞数量,数量超过阈值就调用 Webhook 发送。
3. 只扫 HIGH 和 CRITICAL 级别会不会漏掉漏洞?
会漏掉 MEDIUM 和 LOW,但这样能减少误报和扫描时间。
建议日常巡检锁定高危以上,每周另外安排一次全量扫描,覆盖所有级别。
4. 镜像扫描报告需要保留多久?
没有强制标准,一般保留 30 天到 90 天。
审计类场景建议保留半年以上,同时把报告归档到冷存储,因为累计容量会增长较快。