2026年9月14日
2026年9月14日
DockerイメージをTrivyとSnykで脆弱性スキャンする方法|導入から結果の読み方・CIまで
Dockerイメージには、ベースイメージのOSパッケージや、アプリが使うライブラリが含まれます。これらに既知の脆弱性(CVE)が無いかを調べるのが、イメージの脆弱性スキャンです。この記事では、無料で使えるオープンソースの Trivy と、Snyk社のサービスにつながる Snyk CLI の2つで、Dockerイメージをスキャンする手順を説明します。
コマンドは2026年10月時点の Trivy 0.76.1 で実行して確かめています。Snyk CLI はアカウントの認証が必要なため、公式ドキュメントのコマンドとオプションに沿って書いています。
TrivyとSnykの違い
| 項目 | Trivy | Snyk CLI(Snyk Container) |
|---|---|---|
| 提供元 | Aqua Security(オープンソース) | Snyk(商用サービス、無料プランあり) |
| アカウント | 不要 | 必要(snyk auth で認証) |
| 脆弱性データベース | 実行時にダウンロードしてローカルで照合 | Snyk のサーバーで照合 |
| 主な機能 | イメージ・ファイルシステム・Dockerfile などの設定ミス・シークレットの検出 | イメージの検査、ベースイメージの更新提案、継続監視(snyk container monitor) |
| 利用の上限 | なし | 無料プランは Snyk Container のテスト回数に上限がある(2026年10月時点で100回) |
まず手元やCIで回すなら Trivy、チームでダッシュボードや修正の提案を使いたいなら Snyk、という使い分けができます。両方を併用しても構いません。
Trivy でスキャンする
インストール
Debian・Ubuntu では、Aqua Security の公式 APT リポジトリから入れられます。
sudo apt-get install wget gnupg
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor | sudo tee /usr/share/keyrings/trivy.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb generic main" | sudo tee /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install trivy
trivy --version
macOS では brew install trivy で入ります。インストールせずに、公式のコンテナイメージ(aquasec/trivy)で実行することもできます。
docker run --rm -v trivy-cache:/root/.cache aquasec/trivy:0.76.1 image nginx:alpine
-v trivy-cache:/root/.cache は、脆弱性データベースを毎回ダウンロードし直さないための名前付きボリュームです。
2026年3月の配布物の侵害について
2026年3月19日、Trivy の配布物が攻撃者に改ざんされる事件がありました。Aqua Security の告知によると、対象は次のとおりです。
- Trivy のバイナリ v0.69.4
- Docker Hub のイメージのタグ 0.69.5 と 0.69.6
- GitHub Actions の
aquasecurity/trivy-action(v0.35.0 以外のほぼすべてのタグ)とaquasecurity/setup-trivy
これらを使っていた環境では、パイプラインで使えた認証情報の作り直しが勧められています。これから導入する場合も、次の点を守ってください。
latestではなく、バージョンを指定して入れる(イメージならaquasec/trivy:0.76.1のように書く)- GitHub Actions はタグではなく、コミットの SHA で固定する
- 上記のバージョンが手元やCIのログに残っていないか確認する
詳しくは Aqua Security の告知 を参照してください。
イメージをスキャンする
trivy image nginx:alpine
初回は脆弱性データベースのダウンロードに少し時間がかかります。結果は、OSパッケージ(debian や alpine)と、言語のライブラリ(python-pkg、node-pkg、gobinary など)に分けて、表で表示されます。
表の主な列の意味です。
| 列 | 意味 |
|---|---|
| Library | 脆弱性のあるパッケージ |
| Vulnerability | CVE などの識別子 |
| Severity | 重要度(CRITICAL / HIGH / MEDIUM / LOW / UNKNOWN) |
| Status | fixed は修正版がある、affected は修正版がまだ無い |
| Installed Version / Fixed Version | 入っているバージョンと、修正されたバージョン |
自分でビルドしたイメージも、名前を指定すれば同じようにスキャンできます。Trivy をコンテナで動かしている場合、ローカルにしか無いイメージを読ませるには -v /var/run/docker.sock:/var/run/docker.sock を付けます。このソケットを渡すとコンテナがホストの Docker を操作できるようになるため、信頼できるイメージにだけ使ってください。
対応すべきものに絞る
全件を表示すると数十件から数百件になることが多いので、重要度と修正版の有無で絞ります。
trivy image --severity HIGH,CRITICAL --ignore-unfixed nginx:alpine
--severity HIGH,CRITICALで、重要度が HIGH と CRITICAL のものだけを表示します--ignore-unfixedで、修正版がまだ出ていないものを除きます(今すぐ更新では直せないため)--pkg-types libraryを付けると、言語のライブラリだけに絞れます(osでOSパッケージだけ)
結果で処理を止める(CI向け)
--exit-code 1 を付けると、条件に合う脆弱性が見つかったときに終了コード1で終わります。CIで「HIGH以上の修正可能な脆弱性があればビルドを失敗させる」には、次のようにします。
trivy image --severity HIGH,CRITICAL --ignore-unfixed --exit-code 1 myapp:1.0
echo $?
--exit-code を付けないと、脆弱性があっても終了コードは0です。
個別に除外する
影響が無いと判断した脆弱性は、スキャンを実行するディレクトリに .trivyignore を置き、IDを1行に1つ書くと除外できます。
# 使っていない機能の脆弱性。2026-12 に再確認する
CVE-2026-23949
除外した理由と見直す時期をコメントで残しておくと、あとで判断をたどれます。
結果をファイルに保存する
trivy image --format json --output trivy-result.json myapp:1.0
--format には table(既定)、json、sarif、cyclonedx などを指定できます。GitHub のコードスキャン画面に取り込むなら sarif を使います。
Dockerfile の設定ミスも調べる
Trivy は、Dockerfile のよくない書き方も検出できます。Dockerfile があるディレクトリで実行します。
trivy config .
たとえば USER の指定が無い Dockerfile では、root で動くことを指摘する DS-0002(HIGH)が表示されます。
Snyk CLI でスキャンする
インストールと認証
Node.js がある環境では npm で入れます。
npm install snyk -g
snyk --version
Node.js が無い Linux では、単体のバイナリを使えます(x86_64 の例。ARM64 は snyk-linux-arm64)。この方法では自動で更新されないので、定期的に入れ直してください。
curl --compressed https://downloads.snyk.io/cli/stable/snyk-linux -o snyk
chmod +x ./snyk
sudo mv ./snyk /usr/local/bin/
次に Snyk のアカウントで認証します。ブラウザが開くので、ログインして許可します。
snyk auth
CI では、Snyk の管理画面で発行したトークンを環境変数 SNYK_TOKEN に入れておくと、snyk auth を実行しなくても認証されます。
イメージを検査する
イメージの検査は snyk container test です。旧記事などで見かける snyk scan image というコマンドはありません。
snyk container test nginx:alpine
Dockerfile を一緒に渡すと、より新しいベースイメージへの切り替え案が表示されます。
snyk container test myapp:1.0 --file=Dockerfile
よく使うオプションです。
| オプション | 内容 |
|---|---|
--severity-threshold=high |
指定した重要度以上だけを表示する(low / medium / high / critical) |
--exclude-base-image-vulns |
ベースイメージ由来のOSパッケージの脆弱性を表示しない |
--platform=linux/arm64 |
マルチアーキテクチャのイメージで対象を選ぶ |
--json-file-output=snyk.json |
画面表示に加えて JSON をファイルに保存する |
--sarif-file-output=snyk.sarif |
SARIF をファイルに保存する |
終了コードは、0が脆弱性なし、1が脆弱性あり、2と3が実行の失敗です。CIでは1のときにビルドを止める、という使い方ができます。
個別に除外する
影響が無いと判断した脆弱性は snyk ignore で除外できます。カレントディレクトリの .snyk ファイルに記録され、期限も付けられます。
snyk ignore --id=SNYK-DEBIAN13-ZLIB-0000000 --expiry=2026-12-31 --reason="該当機能を使っていない"
snyk container test myapp:1.0 --file=Dockerfile --policy-path=.snyk
--id には、検査結果に表示された Snyk の脆弱性IDを指定します(上の値は例です)。
継続して監視する
snyk container monitor を実行すると、イメージの構成が Snyk に登録され、あとから新しい脆弱性が公開されたときに管理画面やメールで知らせてくれます。
snyk container monitor myapp:1.0 --file=Dockerfile
見つかった脆弱性への対応
スキャン結果の多くは、次のどれかで解消します。
- ベースイメージを新しくする: OSパッケージの脆弱性は、ベースイメージのタグを新しいものに変えて作り直すと減ることが多いです。古いディストリビューションやサポートが終わった言語のバージョン(例:
python:3.9)を使っている場合は、サポート中のものへ移します。 - パッケージを更新する:
Fixed Versionに示されたバージョンへ、アプリの依存ライブラリを上げます。 - 不要なものを入れない:
-slimやalpine、distroless のような小さいベースイメージにし、ビルドにだけ必要な道具はマルチステージビルドで最終イメージから外します。 - 影響を判断して除外する: 使っていない機能の脆弱性などは、理由と期限を記録したうえで除外します。
同じイメージでも、新しい脆弱性が公開されると結果は変わります。一度スキャンして終わりにせず、定期的にやり直します。
定期的にスキャンする
サーバーで動かしているイメージを、毎週スキャンして結果を残す cron の例です。crontab -e で追加します。
0 3 * * 1 /usr/bin/trivy image --quiet --severity HIGH,CRITICAL --ignore-unfixed --format json --output /var/log/trivy/myapp-$(date +\%F).json myapp:1.0
- crontab の中では
%が特別な意味を持つので、\%と書きます - 保存先の
/var/log/trivy/は先に作っておきます --quietで進捗表示を出さないようにします
CIに組み込む
GitHub Actions で Trivy を使う場合は、公式アクションをタグではなくコミットの SHA で固定し、上記の侵害で問題のないバージョンを使います。CIのジョブ内で Trivy をインストールして直接実行してもかまいません。
- name: Build image
run: docker build -t myapp:${{ github.sha }} .
- name: Scan image
run: |
trivy image --severity HIGH,CRITICAL --ignore-unfixed --exit-code 1 myapp:${{ github.sha }}
Snyk の場合は、リポジトリのシークレットに SNYK_TOKEN を登録し、ジョブの環境変数として渡したうえで snyk container test を実行します。
よくあるつまずき
| 症状 | 原因と対処 |
|---|---|
snyk: command not found と出る |
インストールされていないか、npm のグローバルの bin が PATH に無い。npm prefix -g で場所を確認する |
snyk scan image がエラーになる |
そのようなコマンドは無い。snyk container test を使う |
Snyk で Authentication failed などと出る |
snyk auth を実行するか、SNYK_TOKEN を設定する |
| Trivy をコンテナで動かすと、ローカルでビルドしたイメージが見つからない | -v /var/run/docker.sock:/var/run/docker.sock を付ける。またはホストに Trivy を入れる |
| 毎回データベースのダウンロードで遅い | キャッシュ(~/.cache/trivy やコンテナの /root/.cache)を残す |
| CIで脆弱性があるのにジョブが成功する | Trivy に --exit-code 1 を付けていない |
まとめ
- Trivy は
trivy image イメージ名、Snyk はsnyk container test イメージ名でスキャンする - 実務では
--severity HIGH,CRITICAL --ignore-unfixedのように、対応できるものに絞って見る - CIでは Trivy の
--exit-code 1、Snyk の終了コード1でビルドを止める - 除外は
.trivyignoreやsnyk ignoreで、理由と期限を残して行う - Trivy は2026年3月に配布物が改ざんされたので、バージョンと GitHub Actions の SHA を固定して使う
関連記事: