Docker镜像安全扫描,检测镜像里面漏洞
很多人在使用 docker pull 拉取镜像后,并没有意识到镜像内部可能存在系统漏洞、过时组件,甚至被误提交的私钥和密码。
Docker镜像安全扫描就是解决这个问题的:在部署前检查镜像中已知漏洞和敏感信息,避免带病上线。
本文使用开源工具 Trivy,带零基础用户在一台装有 Docker 的 Linux 服务器上完成扫描、解读结果和常见排错。
开始前需要准备什么
进行Docker镜像安全扫描前,请确认以下条件:
- 已安装 Docker,并可用
docker version查看客户端和服务端版本。 - 服务器可以访问外网,因为 Trivy 首次运行需要下载漏洞数据库。
- 有可用的镜像名称,可以是本地已拉取的镜像,也可以是远程仓库中的镜像。
Trivy 支持安装在 Linux、macOS 和 Windows,推荐使用二进制安装,也可直接下载官方脚本。
以下命令适用于 Linux 的 x86_64 架构:
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
安装后在终端执行,能得到版本信息:
trivy --version
如果服务器无法访问 GitHub,可用官方推荐的 rpm、deb 包安装,或使用容器方式运行 Trivy,建议以官方文档为准。
镜像漏洞扫描:一条命令得到全量报告
先拉取一个需要检查的镜像,例如:
docker pull nginx:1.25
然后使用 Trivy 扫描镜像漏洞:
trivy image nginx:1.25
首次运行会下载漏洞数据库,耐心等待即可。
扫描完成后,终端会输出表格,列出漏洞编号(如 CVE-2024-xxxxx)、严重程度(CRITICAL、HIGH、MEDIUM、LOW)、受影响的软件包以及是否可修复。
怎么看结果? 如果存在 CRITICAL 或 HIGH 级别的漏洞,建议优先处理;
开发环境可以酌情核对,生产环境一般不建议直接使用。
部分漏洞来自基础镜像,也就是你使用的 nginx 镜像底层操作系统(比如 Debian)的软件包,Trivy 会把它们一并列出。
如果希望输出更多信息,可以加入以下参数:
trivy image --severity HIGH,CRITICAL --format table nginx:1.25
只展示高危及以上级别,查看更集中。
还可以用 --format json 导出 JSON 文件,便于集成到 CI 系统或二次分析。
检测镜像中的密钥泄露
有些镜像在构建时会把 .env、.pem 私钥文件、API Token 复制进去,这些都是安全隐患。
Trivy 支持密钥扫描,但需要下载专门的 secret 配置规则:
trivy image --scanners secret nginx:1.25
不过更常见的做法是直接扫描一个已知包含敏感信息的目录或构建上下文。
因为正式扫描镜像时,如果文件没有被打包进镜像层,就扫不到。
所以推荐在构建前先扫描 Dockerfile 所在目录:
trivy fs ./your-project-dir
这条命令会递归检测项目中的 .env、密钥文件、证书文件等。
如果项目根目录存在以下内容,扫描时会提示风险:
- 私钥文件,如
id_rsa、server.key - 包含
password=,api_key=,token=等模式的文本文件 - 硬编码的数据库连接字符串
当 Trivy 报告 secret 类型风险时,
先确认文件是否真的包含敏感内容,
再决定是否将文件加入 .dockerignore,
或在构建时使用多阶段构建来避免把密钥打到最终镜像里。
实际加固操作与避坑指南
扫描不是终点,发现问题后要能改干净。
根据扫描报告,可以按下面的顺序处理:
- 升级基础镜像版本:比如
nginx:1.25-alpine比nginx:1.25体积更小,但漏洞情况不同,请核对 Trivy 报告后选择合适的基础镜像。 - 删除镜像中的敏感文件:修改 Dockerfile,用
rm -rf /path/to/secret删除没用到的文件。注意:Docker 采用的是分层存储,单纯执行rm只是在新层中删除,原层仍然存在,需要重新构建镜像并在后续停止使用旧镜像。 - 使用多阶段构建:把密钥文件放在构建阶段,把最终运行产物复制到运行阶段,这样密钥不会留在最终镜像里。
容易踩的坑:
- 不要把
trivy的漏洞库自动更新当作高频定时任务,建议每周或每个发布周期扫描一次即可,避免资源浪费。 - 不要把
CRITICAL漏洞当成绝对禁用条件,要结合镜像的实际使用层面判断。比如部分漏洞只影响系统内未运行的组件,但如果攻击面暴露,仍然要尽快修复。 - 用
--ignore-unfixed可以过滤没有官方修复补丁的漏洞,方便区分需要自行打补丁的项:
trivy image --ignore-unfixed nginx:1.25
如何验证扫描效果和常见疑问
如果你执行了上面的命令,最终会看到 Trivy 终端输出退出码。
Trivy 扫描完成后,如果发现漏洞,默认退出码非 0;
但如果只扫描 secret 并且没有发现敏感信息,退出码为 0。
更简单的验证方法是:把扫描结果保存到文件,检查报告数量是否有变化。
trivy image -f json -o result.json nginx:1.25
cat result.json | jq '.Results[].Vulnerabilities | length'
有用户会问:Trivy 能扫描私有仓库中的镜像吗? 可以,
先用 docker login 登录,
或者给 Trivy 配置 registry 认证参数。Docker 官方有没有安全扫描? 有 Docker Scout,
但仓库私有镜像的完整扫描可能与订阅绑定,
具体以 Docker 官方当前政策为准。
如果你正在准备生产环境的镜像安全检查,建议把 Trivy 的 image 扫描和 secret 扫描一起写入 CI 流程,配合 .dockerignore 保持构建上下文干净。
这样每次构建推送前,就能自动发现镜像里的漏洞和密钥泄露,不把安全问题留到上线后。
遇到扫描结果异常时,优先回到 Dockerfile 和基础镜像版本这两个源头上排查。