Dockerイメージのセキュリティを強化するための対策
William Henry
2019年4月17日
0 分で読めますDockerセキュリティレポート「Dockerセキュリティを開発の早期段階に移行する」へようこそ。このレポートは、以下の複数の記事で構成されています。
Dockerイメージのセキュリティを強化するための対策
すべての情報をまとめた、手作りの素敵なPDFレポートをダウンロードすることもできます。
すべての情報をまとめた、手作りの素敵なPDFレポートをダウンロードすることもできます。
適切なベースイメージの選択
この課題への一般的なアプローチは、2種類のベースイメージを用意することです。1つは開発や単体テストに使用し、もう1つは後工程のテストや本番環境で使用します。後工程のテストや本番環境では、コンパイラ(Javacなど)やビルドシステム(Mavenなど)、デバッグツールといったビルドツールは必要ありません。実際、本番環境ではBashさえ不要な場合があります。
基本的なOSイメージと、各種バリアントとの間には大きな違いが見られます。ほとんどの場合、OS一式を含むイメージは必要ありません。Buildahのようなイメージビルドツールを使えば、イメージをゼロから構築し、必要なパッケージとその依存関係だけをインストールできます。これにより、イメージの攻撃対象領域を大幅に縮小できます。たとえば、Pythonパッケージとその依存パッケージ、Pythonアプリケーションだけを含むイメージを検討してみましょう。
Buildahには、Dockerデーモンプロセスが不要という利点もあります。これは、コンテナイメージのビルドにリソースを再利用する大規模なコンテナデプロイプラットフォームにおいて重要です。Dockerデーモンは、通信に使用するオープンソケットを持つ特権プロセスです。Dockerデーモンが悪用されるとノードが侵害され、多くの場合、クラスター全体が侵害される可能性があります。ビルドノードを明示的に隔離するか、Buildahのようなツールを使えば、Dockerデーモンは不要になります。
軽量化されたバージョンや、別のLinuxディストリビューションを選ぶことで、脆弱性の数を減らせます。Alpine Linuxをベースにしたサイズわずか5MBの最小限のDockerイメージ、Alpineベースイメージをスキャンしたところ、既知の脆弱性は見つかりませんでした。ただし、これは主にAlpineプロジェクトがセキュリティアドバイザリープログラムを運用していないためです。そのため、脆弱性が存在しても、公開できる公式アドバイザリーがありません。それでもAlpineは、イメージ構築の土台として非常に軽量で無駄のないベースイメージの好例です。
テストしたAlpineイメージのバージョンでは脆弱性は検出されませんでしたが、セキュリティ上の問題がないとは限りません。Alpine Linuxは、パッチをバックポートする方式を好む他の主要ディストリビューションとは異なる方法で脆弱性に対処します。Alpineでは、イメージを頻繁にリリースし、各リリースでシステムライブラリをアップグレードする方式を採用しています。

上のグラフが示すように、Dockerfile内のベースイメージを変更したり、標準イメージの別のタグを使ったりするだけで、大きな違いが生まれます。
Dockerfileから独自のイメージをビルドする場合は、必要以上に大きなイメージに依存しないようにしましょう。イメージのサイズが小さくなり、依存関係を通じて持ち込まれる脆弱性の数も最小限に抑えられます。

Snykユーザーによるスキャン結果から、Dockerイメージのスキャンの44%で既知の脆弱性が見つかり、より新しく安全なベースイメージが利用可能であることがわかりました。この修正アドバイスはSnyk独自のものです。開発者はDockerイメージをアップグレードして対処できます。より新しく優れたベースイメージを自動でスキャンし、通知することは、ベストプラクティスと言えるでしょう。
マルチステージビルドを使う
マルチステージビルドはDocker 17.05以降で利用できます。読みやすく保守しやすい、最適化されたDockerfileを作成するためのビルド方式です。
マルチステージビルドでは、複数のイメージを使用し、特定のイメージから必要な成果物だけを選択してコピーできます。Dockerfileに複数のFROM文を記述し、それぞれに異なるベースイメージを指定して、あるステージから次のステージへ成果物をコピーできます。不要な成果物は残したままにせず、簡潔な最終イメージを作成できます。
この方法では、イメージを小さくできるだけでなく、イメージに脆弱な成果物が含まれるリスクも大幅に低減できます。別のイメージをベースにしたイメージをさらにベースにする代わりに、マルチステージビルドなら必要な成果物だけを「厳選」し、依存するベースイメージの脆弱性を引き継がずに済みます。マルチステージビルドの方法については、Dockerのドキュメントをご覧ください。
レポートの前半で触れたように、Buildahなどのツールを使い、アプリケーションの実行に必要なパッケージだけを含む最小限の本番イメージを作成する方法もあります。Buildahの詳細は、Buildah.ioとPodman and Buildah for Docker Usersをご覧ください。
イメージの再ビルド
すべてのDockerイメージはDockerfileからビルドされます。Docker Hub上のDockerイメージのDockerfileは、GitHubで公開されています。Dockerfileには、イメージ作成時に通常手作業で行う手順を自動化するための命令が記述されています。また、ライブラリのインポートやカスタムソフトウェアのインストールも可能です。これらはすべてDockerfileの命令です。State of Open Source Security 2019レポートでは、脆弱性のあるDockerイメージの20%は、イメージを再ビルドするだけで問題を解消できることがわかりました。
イメージのビルドは、基本的にその時点のイメージのスナップショットを作成することです。厳密なタグを指定せずにベースイメージに依存している場合、再ビルドのたびにベースイメージが異なる可能性があります。パッケージインストーラーでパッケージをインストールしている場合も、再ビルドによってイメージが変わることがあります。
次の内容を含むDockerfileでは、再ビルドのたびに異なるバイナリが使われる可能性があります。FROM ubuntu:latestRUN apt-get -y update && apt-get install -y python
すでに修正済みの既知の脆弱性がイメージに残らないよう、Dockerイメージは定期的に再ビルドしてください。再ビルド時には、キャッシュを使わず新しいファイルをダウンロードするために、--no-cacheオプションを使用します。
例:docker build --no-cache -t myImage:myTag myPath/
まとめると、イメージを再ビルドする際は、次のベストプラクティスに従いましょう。
各コンテナの役割は1つだけにする。
コンテナはイミュータブルで、軽量かつ高速にする。
コンテナ内にデータを保存しない(共有データストアを使用する)。
コンテナは簡単に破棄して再ビルドできるようにする。
小さなベースイメージ(Linux Alpineなど)を使用する。eÌ イメージは小さいほど配布が簡単です。
不要なパッケージのインストールを避ける。
イメージをすっきり整理し、安全に保てます。
ビルド時にキャッシュを使わない。
本番環境に脆弱なコンテナをデプロイしないよう、Snykのコンテナスキャンなどのツールでデプロイ前にイメージを自動スキャンする。
開発中も本番環境でも、イメージを毎日スキャンして脆弱性を確認する。その結果に基づき、必要に応じてイメージの再ビルドを自動化する。
開発中のイメージスキャン
Dockerfileからイメージを作成したり、イメージを再ビルドしたりすると、システムに新たな脆弱性が持ち込まれる可能性があります。先述のとおり、ユーザーの68%は、開発者にもコンテナセキュリティに対する相応の責任があると考えています。脆弱性をできるだけ早期に検出するため、開発中にDockerイメージをスキャンすることをワークフローに組み込みましょう。
セキュリティを開発の早期段階に移行するには、開発者がリポジトリやビルドパイプラインにコミットする前に、ローカルマシンでDockerfileとイメージをスキャンできるのが理想的です。
これは、CIパイプラインでのスキャンをローカルスキャンに置き換えるという意味ではありません。開発のあらゆる段階でスキャンを実施し、できれば自動化することが望ましいということです。ビルド中、レジストリへのイメージのプッシュ前、本番環境へのデプロイ前に自動スキャンを行うことを検討しましょう。自動スキャンで新たな脆弱性が見つかった場合に、イメージのレジストリへの登録や本番環境へのデプロイを拒否することは、ベストプラクティスと見なすべきです。
Snykが最近リリースしたコンテナ脆弱性管理では、イメージのレイヤーを抽出し、パッケージマネージャーのマニフェスト情報を調べてDockerイメージをスキャンします。その後、イメージにインストールされたすべてのOSパッケージをDocker脆弱性データベースと照合します。さらに、イメージにインストールされた主要なバイナリのスキャンも欠かせません。Snykは、dpkg、RPM、APKなどのOSパッケージマネージャーではなく、RUNコマンドなど別の方法でインストールされることの多い主要なバイナリのスキャンにも対応しています。
開発者がローカルマシンで開発中にDockerfileやイメージをスキャンできるツールを提供することで、保護の層がもう一つ加わり、開発者はシステム全体のセキュリティ強化に積極的に貢献できます。
本番環境でのコンテナスキャン
調査回答者の91%が、本番環境でDockerイメージをスキャンしていないことがわかりました。コンテナを積極的にチェックしていれば、新たな脆弱性が発見され、本番システムが危険にさらされた場合の大きなトラブルを未然に防げます。
Snykのコンテナ監視機能を使えば、Dockerイメージを定期的(たとえば毎日)にスキャンできます。Snykはイメージの依存関係のスナップショットを作成し、継続的に監視します。
さらに、ランタイム監視も有効にしましょう。ランタイム内の未使用モジュールやパッケージをスキャンすると、イメージを小さくする方法がわかります。未使用のコンポーネントを削除すれば、システムライブラリとアプリケーションライブラリに不要な脆弱性が入り込むのを防げます。また、イメージの保守も容易になります。
続きを読む:
Dockerイメージのセキュリティを強化するための対策
DockerでNode.jsウェブアプリケーションをコンテナ化するためのベストプラクティス10選 - Node.js開発者なら、Node.jsアプリケーション向けに安全で高性能なDockerベースイメージを構築する方法を手順ごとに解説するこの記事がきっと役立ちます。
Dockerセキュリティのベストプラクティス10選 - Dockerベースイメージの構築時や取得時に従うべきセキュリティ対策を詳しく解説し、Docker Content Trustについても紹介します。
Java開発者の方には、こちらの記事がおすすめです。Java開発者のためのDocker:セキュリティを損なわないために知っておくべき5つのこと
