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

見つかった脆弱性への対応

スキャン結果の多くは、次のどれかで解消します。

  1. ベースイメージを新しくする: OSパッケージの脆弱性は、ベースイメージのタグを新しいものに変えて作り直すと減ることが多いです。古いディストリビューションやサポートが終わった言語のバージョン(例: python:3.9)を使っている場合は、サポート中のものへ移します。
  2. パッケージを更新する: Fixed Version に示されたバージョンへ、アプリの依存ライブラリを上げます。
  3. 不要なものを入れない: -slim や alpine、distroless のような小さいベースイメージにし、ビルドにだけ必要な道具はマルチステージビルドで最終イメージから外します。
  4. 影響を判断して除外する: 使っていない機能の脆弱性などは、理由と期限を記録したうえで除外します。

同じイメージでも、新しい脆弱性が公開されると結果は変わります。一度スキャンして終わりにせず、定期的にやり直します。

定期的にスキャンする

サーバーで動かしているイメージを、毎週スキャンして結果を残す 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 を固定して使う

関連記事:

お気軽にご相談ください

お見積りへ お問い合わせへ
▲