イメージ検査のベストプラクティス

このページで扱うのは、検査に対する推奨とベストプラクティス、そして、安全なイメージの構築です。

開発ワークフロー内で当たり前のような(ネイティブな)安全さをもたらすため、Docker と Snyk は提携しました。そのために提供するのは、安全なコンテナを構築・デプロイするために、開発者に対するシンプルで一直線な手法です。コンテナの安全性には、開発、セキュリティ、運用といった、複数のチームに亘ります。さらに、コンテナに対して適用される、複数レイヤーのセキュリティもあります。

  • コンテナ イメージと、中で実行しているソフトウェア
  • コンテナ、ホストオペレーティングシステム、同じホスト上にある他のコンテナとの間でのやりとり
  • ホストオペレーティングシステム
  • コンテナのネットワーク機能とストレージ

既存の Docker プラットフォームを拡張し、脆弱性検査のオプションを導入すると、脆弱性検出の手順に慣れ、かつ、開発プロセスの初期で脆弱性の修正を可能にします。手順はシンプルで継続的に確認します。たとえば、バックグラウンドで Snyk Advisor を使ってイメージをチェックすると、Docker Hub 上にあるいくつかの脆弱性も確認できます。この結果、CI サイクルを短くし、開発から本番環境への信頼性を高めます。

開発者のセキュリティ ジャーニー

イメージ検査

重要

Log4j 2 CVE-2021-44228

docker scan のバージョン v0.11.0 未満は Log4j 2 CVE-2021-44228 を検出できません。Docker Desktop を更新するため、バージョン 4.3.1 以上をインストールして、この問題に対応します。詳しい情報は Scan images for Log4j 2 CVE をご覧ください。

Docker Hub へのイメージ送信をトリガとした、自動的な検査も可能です。そのためには、 CLI で docker scan コマンドを通してか、 Docker Hub 上を通してかのどちらかで行います。

CLI を使って検査

イメージを構築したら、 Docker Hub にイメージを送る前に、 docker scan コマンドを実行します。CLI を使ったイメージ検査の手順詳細は、 docker scan をご覧ください。

脆弱性検査

Docker Hub を使って検査

Docker Hub を通した脆弱性検査、表示、調査のトリガを設定できmさう。詳しい情報は、 Hub 脆弱性検査 をご覧ください。

注釈

Docker Hub 脆弱性検査が利用可能なのは、 Docker Pro、Team、Business を契約している開発者のみです。料金プランに関する詳しい情報は Docker Pricing をご覧ください。

脆弱性検査のサマリ

Docker Desktop で検査のサマリを表示

Docker Desktop では、 Docker ダッシュボード上で脆弱性の状態についてのスナップショットを表示します。イメージの上にマウスカーソルを異動し、 View in Hub をクリックすると、 Docker Hub 上で脆弱性報告の詳細を表示します。

ベストプラクティス

開発者であれば、コンテナの安全性を改善するため、いくつかのシンプルなステップがあります。

  1. 提供元が信頼できて、かつ、小さく維持できる、正しいベースイメージの選択
  2. マルチステージ ビルドの使用
  3. イメージの再構築
  4. 開発中のイメージを検査
  5. 本番環境でイメージを検査

それでは、これら各ベストプラクティスの詳細をそれぞれみましょう。

正しいベースイメージの選択

安全なイメージを達成するための第一のステップが、正しいベースイメージの選択です。イメージの選択時、信頼できる提供元によって構築され、かつ、小さく維持できるイメージを確保します。

Docker Hub には 830 万以上のリポジトリがあります。この中のイメージのいくつかが Docker によって提供されている 公式イメージ(Official Image) であり、これは、Docker が企画したオープンソースのソリューションを集めたリポジトリです。また、 Docker は Verified Publisher(認定パブリッシャー) が公開するイメージも提供します。これらの高品質なイメージは、 Docker と提携した組織によってメンテナンスされており、Docker が各リポジトリの信頼性を検証しているものです。ベースイメージを選ぶには、 Official Image (公式イメージ)と Verified Publisher (認定パブリッシャー)のバッジが付いているものを探してください。

Docker Hub 公式イメージ

Dockerfile から自分のイメージを構築しようとする時は、自分の必要条件に一致する、最小のベースイメージを確保します。より小さなベースイメージはポータビリティと早いダウンロードをもたらすだけでなく、イメージの容量を圧縮し、依存関係を通して発生する脆弱性の数を最小化します。

また、私たちが勧めるのは、2種類のベースイメージの使用です。1つめのイメージは開発とユニットテスト用であり、2つめのイメージは構築の最終段階のテストおよび本番用です。後の構築段階では、コンパイラ、構築システム、デバッグ用ツールといった、いくつかの構築用ツールは不要となるでしょう。小さなイメージは依存関係が最小のため、攻撃に晒される危険性が低いと考えられます。

マルチステージ ビルドの使用

マルチステージ ビルド(multi-stage build) は、読みやすく維持を簡単が簡単になるよう最適化された Dockerfile を作成するために設計されています。マルチステージ ビルドがあれば、複数のイメージを使えるようになり、対象のイメージから必要となるアーティファクト(成果物)のみを選んでコピーできます。

Dockerfile 内で複数の FROM 記述が行え、 FROM ごとに異なるベースイメージが利用できます。また、あるステージから別のステージへと、アーティファクトを選んでコピーできますので、最終イメージに不要なものを放置できます。

この手法で作成されたあらゆるイメージは、複雑さを著しく減らしますが、イメージ内に脆弱性のあるアーティファクトを含んでしまう可能性も変えます。つまり、出来合いのイメージを使ってイメージを構築するのではなく、マルチステージ ビルドによって、ベースイメージへの依存に由来する脆弱性を継承しないよう、必要なものだけを「えり好み」できます。

マルチステージ ビルドの設定の仕方に関する情報は、 マルチステージ ビルド をご覧ください。

イメージの再構築

Docker イメージは Dockerifle から構築します。Dockerfile の内容には、通常(手動で)イメージを作成する手順を、自動的に行えるようにするための命令が入っています。さらに、いうつかのライブラリの読み込みや、任意のソフトウェアをインストールできます。これらは Dockerfile 内で命令として見えます。

イメージの構築とは、その時点におけるイメージのスナップショットです。タグを使わないベースイメージに依存していると、再構築するたびに異なるベースイメージを使う可能性があります。また、パッケージのインストールにパッケージのインストーラを使おうとしても、再構築後のイメージが劇的に変わってしまう可能性があります。例として、以下のようなエントリがある Dockerfile では、再構築するたびに異なるバイナリができる可能性があります。

FROM ubuntu:latest
RUN apt-get -y update && apt-get install -y python

私たちが推奨するのは、 Docker イメージに既知の脆弱性が入り込むのを防いでの再構築です。再構築時に --no-cache オプションを使うと、キャッシュの一致を防止するため、全体を真っ新な状態からダウンロードします。

例:

$ docker build --no-cache -t myImage:myTag myPath/

イメージの再構築時は、以下のベストプラクティスに従うのを検討します。

  • 各コンテナは1つの役割のみを持たせるべき
  • コンテナは 不変(immutable)軽量(lightweight)高速(fast) であるべき
  • コンテナ内にデータを保管しない。かわりに共有データストアを使う
  • コンテナは破棄や再構築が簡単であるべき
  • 小さなベースイメージを使う(Linux Alpine のような)。小さなイメージは配布が簡単
  • 不要なパッケージのインストールを避ける。これはイメージをクリーンかつ安全に保つ
  • 再構築時にキャッシュとの一致を避ける
  • 脆弱性のあるコンテナを本番環境に送信するのを防ぐため、デプロイ前にイメージを自動検査する
  • 開発と本番環境との両方で、イメージの脆弱性を毎日検査。このベースとなるため、必要に応じてイメージの再構築を自動化

ベストプラクティスの詳細や効率的なイメージの構築手法については、 Dockerfile ベストプラクティス をご覧ください。

開発中にイメージを検査

Dockerfile からイメージを構築すると、イメージの再構築によって、システム内に新しい脆弱性を招く可能性があります。開発課程内の初期に脆弱性を把握するため、開発中は Docker イメージの検査を、ワークフローの一部とすべきです。開発サイクルのどの段階でもイメージ検査が行えますし、理想としては自動検査を検討します。たとえば、 Docker Hub (あるいは他のレジストリ)にイメージを送信する前に、構築処理の間で自動検査をするよう設定を検討します。そして、最終的に検査済みのイメージが本番環境へ送信される前に行われます。

本番環境でのイメージ検査

積極的なコンテナの確認は、新しい脆弱性が発見されたとしても、それ以外は本番環境システムでの危険性に対する悩みとはならないため、イライラさせられるのを抑えられるでしょう。

Docker イメージの定期的な検査には、可能であればコンテナに対応した Snyk monitor を使います。 Snyk はイメージのスナップショットを作成し、依存関係を継続的に監視します。さらに、ランタイムの監視も活発にすべきです。未使用モジュールとランタイム内の検査によって、イメージに対する危険性を減らす気付きが得られるでしょう。使っていないコンポーネントの削除は、システムとアプリケーション ライブラリの両方で、不要な脆弱性を防ぎます。そうすると、イメージのメンテナンスがより簡単にもなります。

まとめ

安全なイメージ構築は、継続的な過程です。効率的、スケーラブル、安全なイメージの計画および構築の為、このガイドで強調した推奨やベストプラクティスを検討しましょう。

このガイドでの学びを振り返ります。

  • 信頼できるベースイメージから始める。ベースイメージの選択時は、公式イメージと認定パブリッシャーのバッジがついているかどうかを忘れない
  • コードとその依存関係を安全にする
  • 必要なパッケージのみを含み、ベースイメージが最小となるよう検討すうr
  • イメージを最適化するため、マルチステージ ビルドを使う
  • 安全のため、イメージに追加するツールや依存関係を、注意深く監視や管理する
  • 安全のため、開発ライフサイクルの間は、複数のステージでイメージを検査する
  • イメージの脆弱性を頻繁に確認する

さらに詳しく

Snyk から提供されている以下の記事もご覧いただけます。

参考

Best practices for scanning images
https://docs.docker.com/develop/scan-images/