Docker镜像漏洞定期扫描安全巡检脚本
为什么需要定期扫描 Docker 镜像漏洞
生产环境中使用的 Docker 镜像可能包含已知的高危漏洞(CVE)。
即使拉取时没问题,基础镜像更新后也可能出现新漏洞。
手动检查费时且容易遗漏,因此需要一套自动化脚本定期扫描所有镜像,并在发现漏洞时通知运维人员。
本文以 Trivy 为例,因为它免费、轻量、无需数据库,适合新手。
最终脚本会扫描本地所有镜像,输出报告并记录日志,方便追溯。
准备工作:安装 Trivy 并确认环境
在开始前,确保服务器已安装 Docker,并且当前用户有 docker 命令执行权限。
安装 Trivy(Linux x86_64)
# 下载最新稳定版
wget https://github.com/aquasecurity/trivy/releases/latest/download/trivy_0.57.1_Linux-64bit.deb
# 安装(Ubuntu/Debian)
sudo dpkg -i trivy_0.57.1_Linux-64bit.deb
# 验证安装
trivy --version
CentOS/RHEL 用户可下载 RPM 包,或用二进制文件直接解压到 /usr/local/bin。
安装后务必用 trivy image --help 测试命令是否可用。
编写定期扫描巡检脚本
脚本目标:扫描本地所有镜像,将结果保存到 /var/log/trivy-scan 目录,并以 JSON 格式记录最新扫描。
同时输出一份人类可读的摘要。
在 /usr/local/bin 创建脚本文件 docker-scan-check.sh:
#!/bin/bash
# Docker镜像漏洞定期扫描安全巡检脚本
LOG_DIR="/var/log/trivy-scan"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $LOG_DIR
# 获取所有本地镜像名称(不重复)
IMAGES=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep -v "" | sort -u)
for img in $IMAGES; do
echo "Scanning: $img"
# 使用--severity指定严重级别,--format json输出机器可读报告
trivy image --severity CRITICAL,HIGH --format json "$img" > "$LOG_DIR/${img//\//_}_${DATE}.json" 2>/dev/null
# 同时生成短摘要(仅显示高危以上)
trivy image --severity CRITICAL,HIGH --format table "$img" 2>/dev/null | tail -n +5 >> "$LOG_DIR/summary_${DATE}.txt"
done
echo "Scan completed at $DATE, reports saved to $LOG_DIR"
注意: 如果镜像名包含斜杠 /,上述脚本将其替换为下划线避免路径错误。
首次执行建议先手动跑一行 docker images 确认镜像列表无误。
授予执行权限:
sudo chmod +x /usr/local/bin/docker-scan-check.sh
设置定时任务自动执行
使用 cron 实现每周日凌晨 2 点自动扫描一次。
编辑当前用户的 crontab:
crontab -e
添加一行(每天凌晨 2:00 扫描,推荐每周一次即可):
0 2 * * 0 /usr/local/bin/docker-scan-check.sh >> /var/log/trivy-scan-cron.log 2>&1
保存后,用 crontab -l 确认。
如果系统未安装 cron,先执行 sudo apt install cron(Debian)或 sudo yum install cronie(CentOS)。
避坑指南:常见问题与解决方法
1. Trivy 扫描慢或卡住
首次扫描会下载漏洞数据库(约 200MB),建议在空闲时间执行。
如果网络不稳定,可以手动先跑 trivy image --download-db-only 提前下载。
2. 镜像名带斜杠导致 JSON 文件保存失败
脚本中已经处理:将 / 替换为 _。
如果仍然失败,检查 docker images 输出中是否有 tag 为 的镜像,这些镜像不应纳入扫描(脚本已排除)。
3. 权限不足
Trivy 默认以当前用户运行。
如果使用 root 的 cron,需确保 PATH 包含 trivy 命令;
如果用普通用户,需将 trivy 添加至该用户 PATH 或使用绝对路径。
4. 大量镜像导致磁盘空间不足
每个镜像生成一个 JSON 报告,长期积累会占用空间。
建议在脚本末尾增加过期清理逻辑,例如只保留最近 7 天的报告:
find $LOG_DIR -name "*.json" -mtime +7 -delete
find $LOG_DIR -name "summary_*.txt" -mtime +7 -delete
验证扫描是否正常执行
等待第一个定时任务触发,或手动立即执行:
sudo /usr/local/bin/docker-scan-check.sh
执行完成后,检查输出目录:
ls -la /var/log/trivy-scan/
# 应该看到类似 busybox_latest_20250317_020000.json 和 summary_20250317_020000.txt
查看摘要文件:
cat /var/log/trivy-scan/summary_20250317_020000.txt
若显示无漏洞,说明当前镜像安全。
如果出现 CRITICAL/HIGH 漏洞,则需要根据 CVE 编号更新基础镜像或打补丁。
常见问题解答
Q:Trivy 和 Docker Scout 哪个更好?
Trivy 免费、离线友好、支持多格式输出;
Docker Scout 需 Docker Desktop 及账号。
对于服务器端自动化巡检,Trivy 更合适。
Q:可以扫描私有仓库的镜像吗?
可以,先在本地 docker pull 下来,再扫描本地镜像。
脚本会自动识别所有本地已拉取的镜像。
Q:怎样在扫描到高危漏洞时发送通知?
在脚本中添加条件判断,如果 JSON 报告中 Results[].Vulnerabilities 不为空,则调用邮件或 Webhook。
可参考 Trivy 的 --format sarif 输出,再与告警系统对接。
小结
通过本文的 Docker 镜像漏洞定期扫描安全巡检脚本,你已经可以用 Trivy + cron 实现每周自动扫描,并将结果保留成结构化日志。
后续可根据业务需求调整扫描频率、告警方式以及镜像过滤规则。
建议首次部署后连续观察两次扫描结果,确认脚本稳定运行后再正式纳入日常运维流程。