
Docker 镜像上线前先体检用 Trivy 扫漏洞和密钥再用 cpolar 临时分享安全报告有些 Docker 应用在局域网里跑得挺顺一到上线前才发现镜像里带着高危 CVE项目目录里还残留了测试密钥。这个坑很常见服务能启动不代表它适合交给别人访问。这篇就做一件事在本地或 NAS 上用 Trivy 给镜像和 compose 项目做一次上线前体检把漏洞、配置问题、Secrets 扫出来再把报告做成只读静态页面用 cpolar 开一个临时 HTTPS 地址给手机或同事看。重点不是把报告长期挂公网而是让验收沟通更省事。1 什么是 Trivy这篇里它负责扫什么Trivy 是 Aqua Security 维护的开源安全扫描工具。官方文档里明确支持扫描容器镜像、文件系统、代码仓库、配置文件、Secrets、许可证和 SBOM 等目标。在这篇教程里我们只用它做 4 件实用的事扫 Docker 镜像里的系统包和应用依赖漏洞扫项目目录里的依赖锁文件、Dockerfile、docker-compose.yml扫项目里误提交的密钥、Token、私钥片段输出 JSON 报告再转换成一个可打开的 HTML 页面这里先说清楚边界Trivy 负责发现风险不负责替你修复业务代码。看到 HIGH、CRITICAL 之后要回到镜像版本、基础镜像、依赖版本和配置权限里处理。2 环境准备准备 Docker、Trivy 和一个报告目录这套流程适合 macOS、Linux、NAS SSH 环境。Windows 用户也可以在 WSL 里按 Linux 命令跑路径写法保持 Linux 风格更顺手。2.1 安装 TrivymacOS 直接用 Homebrewbrew install trivy trivy --versionLinux 可以用 Trivy 官方仓库里的安装脚本安装到/usr/local/bincurl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sudo sh -s -- -b /usr/local/bin trivy --version如果你只想在 Docker 环境里跑 Trivy也可以直接拉官方镜像docker pull aquasec/trivy:latest注意扫描本机 Docker 镜像时最省事的做法还是安装 Trivy CLI。把 Docker socket 挂进扫描容器也能工作但这会把宿主机 Docker 控制口交给容器个人测试少用团队环境别默认这样干。2.2 准备项目目录这里用一个常见目录演示你可以替换成自己的 compose 项目mkdir -p ~/docker-security-check/reports cd ~/docker-security-check cat docker-compose.yml EOF services: web: image: nginx:1.27-alpine ports: - 8080:80 EOF这一步不是为了搭一个复杂服务而是准备一个能被扫描、能被托管报告验证的最小现场。后面换成你的真实项目时只要保留reports目录即可。3 扫描 Docker 镜像先看上线对象干不干净镜像是最应该先扫的对象。很多人只看容器能不能启动却忽略基础镜像里的系统包和应用依赖。先拉取示例镜像docker pull nginx:1.27-alpine执行漏洞和密钥扫描trivy image nginx:1.27-alpineTrivy 默认会启用漏洞和 Secrets 扫描。结果里重点看这几列Severity风险等级重点处理CRITICAL和HIGHInstalled Version当前镜像里安装的版本Fixed Version安全修复版本升级时优先对照它Title漏洞标题用来判断影响组件如果只想看高危和严重问题用下面这条命令压缩输出trivy image --severity HIGH,CRITICAL nginx:1.27-alpine如果输出为空说明当前筛选条件下没有命中 HIGH 和 CRITICAL。这里别急着宣布“绝对安全”只能说明这次扫描范围内没有对应级别的发现。私有镜像仓库要先登录。官方推荐用trivy registry login它会把凭据写入 Docker 配置文件避免把密码直接放在命令参数里cat ~/registry-password.txt | trivy registry login --username your_user --password-stdin ghcr.io trivy image ghcr.io/your-org/your-image:1.0.0提醒一下不要把真实密码写进 Shell 历史记录也不要把含有凭据的报告截图直接发到群里。4 扫描项目目录把 compose、Dockerfile 和依赖文件一起查镜像扫描只能看到已经打包进去的内容。上线前还要扫项目目录因为风险经常藏在Dockerfile、docker-compose.yml、.env、依赖锁文件里。在项目根目录执行cd ~/docker-security-check trivy fs .trivy fs会扫描本地文件系统。官方文档说明文件系统扫描默认启用漏洞和 Secrets 扫描会根据package-lock.json、Gemfile.lock、Pipfile.lock等锁文件识别依赖漏洞。配置风险需要手动打开 misconfig 扫描trivy fs --scanners vuln,secret,misconfig .这条命令适合上线前跑一遍。它会把依赖漏洞、密钥痕迹、Dockerfile 或 compose 配置问题放到同一份结果里排查起来更直接。如果你只关心配置文件也可以单独扫配置trivy config .这里别把扫描当成形式。看到 compose 里有特权模式、root 用户、敏感目录挂载、明文环境变量就回到配置里改掉。家庭服务器和 NAS 也一样越是长期运行的小服务越要把权限收窄。5 生成 JSON 和 HTML 报告让别人不用翻终端终端输出适合自己排查不适合发给同事验收。这里把 Trivy 输出成 JSON再用一段 Python 生成静态 HTML 报告。先生成两份 JSONcd ~/docker-security-check mkdir -p reports trivy image --format json --output reports/image-nginx.json nginx:1.27-alpine trivy fs --scanners vuln,secret,misconfig --format json --output reports/project-fs.json .再写一个转换脚本cat reports/render_trivy_html.py PY import html import json from pathlib import Path report_files [ (镜像扫描, Path(image-nginx.json)), (项目目录扫描, Path(project-fs.json)), ] rows [] for group, file_path in report_files: data json.loads(file_path.read_text(encodingutf-8)) for result in data.get(Results, []): target result.get(Target, ) for item in result.get(Vulnerabilities, []): rows.append([ group, target, item.get(Severity, ), item.get(VulnerabilityID, ), item.get(PkgName, ), item.get(InstalledVersion, ), item.get(FixedVersion, ), item.get(Title, ), ]) for item in result.get(Misconfigurations, []): rows.append([ group, target, item.get(Severity, ), item.get(ID, ), item.get(Type, misconfig), , , item.get(Title, ), ]) for item in result.get(Secrets, []): rows.append([ group, target, item.get(Severity, ), item.get(RuleID, ), secret, , , item.get(Title, ), ]) def esc(value): return html.escape(str(value or )) body \n.join( tr .join(ftd{esc(col)}/td for col in row) /tr for row in rows ) html_doc f!doctype html html langzh-CN head meta charsetutf-8 titleTrivy 安全扫描报告/title style body {{ font-family: -apple-system, BlinkMacSystemFont, Segoe UI, sans-serif; margin: 32px; }} table {{ border-collapse: collapse; width: 100%; font-size: 14px; }} th, td {{ border: 1px solid #ddd; padding: 8px; vertical-align: top; }} th {{ background: #f5f5f5; }} .CRITICAL, .HIGH {{ color: #b00020; font-weight: 700; }} /style /head body h1Trivy 安全扫描报告/h1 p报告只用于上线前验收沟通请勿长期公开。/p table theadtrth来源/thth目标/thth等级/ththID/thth组件/thth当前版本/thth修复版本/thth标题/th/tr/thead tbody{body}/tbody /table /body /html Path(index.html).write_text(html_doc, encodingutf-8) print(f生成完成index.html共 {len(rows)} 条发现) PY cd reports python3 render_trivy_html.py如果脚本提示 JSON 文件不存在先检查上一步 Trivy 命令有没有成功写入reports/image-nginx.json和reports/project-fs.json。路径别填错很多问题都出在当前目录不对。6 用 Nginx 临时托管报告只暴露静态文件报告已经是静态 HTML用 Nginx 临时托管最干净。我们只挂载reports目录不挂载 Docker socket不开放宿主机管理口。cd ~/docker-security-check docker run --rm --name trivy-report-web \ -p 18080:80 \ -v $PWD/reports:/usr/share/nginx/html:ro \ nginx:1.27-alpine另开一个终端验证本地访问curl -I http://127.0.0.1:18080/看到HTTP/1.1 200 OK就说明报告页面已经由 Nginx 提供服务。浏览器打开http://127.0.0.1:18080/能看到刚才生成的Trivy 安全扫描报告。这里的关键点是:ro表示只读挂载。别人访问页面时只能看报告不能通过这个 Nginx 容器改你的报告文件。7 用 cpolar 临时分享报告给手机或同事验收本地报告能打开后再用 cpolar 做临时 HTTPS 分享。这个切入点很适合上线前沟通你不用把报告上传到网盘也不用把整个 NAS 面板暴露出去只给一个只读报告页面。cpolar 安装入口可以从官网获取官网https://www.cpolar.com/下载页https://www.cpolar.com/download文档https://www.cpolar.com/docs/Linux 官方一键安装命令如下curl -L https://www.cpolar.com/static/downloads/install-release-cpolar.sh | sudo bashmacOS 用 Homebrew 安装brew tap probezy/core brew install cpolar安装后先确认本地管理端可用cpolar version curl -s http://127.0.0.1:9200 || echo cpolar 服务未启动如果已经登录并配置好 cpolar直接开 HTTP 隧道到18080cpolar http 18080终端会输出一个公网访问地址。把这个 HTTPS 地址发给同事或用手机打开就能看到刚才的 Trivy 报告。免费随机地址 24 小时内会变化固定二级子域名需要基础套餐或以上。本文场景是临时验收用随机地址已经够用。需要长期稳定地址时再按团队规范申请固定二级子域名。8 上线前安全边界这些口子别顺手打开这一步很重要。我们分享的是扫描报告不是分享服务器控制权。建议按下面几条做只暴露18080这个静态报告端口不暴露 Docker API、Portainer、SSH、NAS 管理后台报告里出现 Token、私钥、内部域名时先处理泄漏源再分享脱敏后的报告验收结束后关闭cpolar http 18080对应进程并停止 Nginx 报告容器报告不要长期公开内部流转也要控制范围停止报告容器很简单在运行 Nginx 的终端按CtrlC。如果你把容器放到了后台运行就执行docker stop trivy-report-web如果 cpolar 是前台运行同样在对应终端按CtrlC。临时验收结束就收口别让报告页面挂着过夜。9 总结现在这条链路已经跑通了Trivy 负责把镜像、项目目录、配置文件和 Secrets 做上线前体检Nginx 负责把报告变成只读页面cpolar 负责把这个页面临时分享给手机或同事验收。整个过程没有暴露 Docker socket也没有开放宿主机管理入口。实际使用时记住这几个关键点上线前先扫镜像再扫项目目录镜像和源码两边都要看报告用 JSON 留档用 HTML 沟通终端输出只适合自己排查cpolar 只用于临时分享只读报告用完关闭隧道和报告容器我更推荐把这套流程做成上线前固定动作。哪怕只是家用服务器或 NAS 上的小服务提前扫一遍也能少很多隐患等以后接入 CI再把trivy image和trivy fs放进流水线里风险就不会堆到发布当天才爆出来。