Node.js開発者がDockerでセキュリティを損なわないために知っておくべき5つのこと
2021年1月25日
0 分で読めますDockerでは、コンテナイメージのダウンロード数が累計500億回を超えています。Docker Hubには何百万ものアプリケーションが公開されており、コンテナベースのアプリケーションは広く普及しています。アプリケーションを簡単に利用・公開できるのも、その理由です。
とはいえ、独自のDocker Node.js Webアプリケーションを安易に構築すると、多くのセキュリティリスクが伴う可能性があります。Dockerを使うNode.js開発者にとって、セキュリティを欠かせない要素にするにはどうすればよいでしょうか。
Docker for Node.jsの概要とDockerイメージの構築に入る前に、このテーマについてよく寄せられる質問を見てみましょう。
Node.jsアプリケーションをDocker化するにはどうすればよいですか?
Node.jsアプリケーションをDockerコンテナで実行するには、プロジェクトのディレクトリをコピーして必要なnpmパッケージをすべてインストールするだけで済む場合もあります。しかし、見落としがちなセキュリティや本番環境に関する考慮事項が数多くあります。DockerでNode.js Webアプリケーションをコンテナ化する方法を解説した次のガイドでは、本番環境に適したヒントを紹介しています。適切なDockerベースイメージの選択やマルチステージビルドの活用から、シークレットの安全な管理、本番環境向けのフレームワーク設定の適切な有効化までを網羅しています。
この記事では、Webアプリケーションに適したNode.js Dockerベースイメージを選ぶことの影響を理解し、アプリケーションで利用できる最も安全なDockerイメージを見つけるために必要な情報を解説します。
DockerはNode.js開発者にどのように役立ちますか?
Node.jsアプリケーションをコンテナにパッケージ化すると、ランタイム、設定、OSレベルの依存関係など、アプリケーション全体をまとめられます。WebアプリケーションをさまざまなプラットフォームやCPUアーキテクチャで実行するために必要なものも、すべて含めることができます。これらのイメージは、コンテナイメージと呼ばれるデプロイ可能な成果物としてパッケージ化されます。Dockerイメージは、再現性の高いビルドを簡単に実現するソフトウェアのバンドルであり、Node.js開発者は同じプロジェクトや製品をあらゆる環境で実行できます。
さらに、Dockerコンテナを使えば、特別な権限やプロジェクト実行専用の環境を用意せずに、プラットフォームの新しいリリースやその他の変更を簡単に試すことができます。
1. アプリケーションに適したNode.js Dockerベースイメージを選ぶ
Node.jsプロジェクト用のDockerイメージを作成するときは、Docker Hubから取得した別のDockerイメージをベースに、独自のアプリケーションイメージを構築します。この元となるイメージをベースイメージと呼びます。ベースイメージは、Node.jsアプリケーション用の新しいDockerイメージを構築する際の土台です。
ベースイメージの選択は非常に重要です。Dockerイメージのビルド速度だけでなく、Webアプリケーションのセキュリティやパフォーマンスにも大きく影響します。DebianやUbuntuをベースにしたフル機能のOSイメージを選ぶこともあるでしょう。イメージに含まれるすべてのツールやライブラリを利用できるためです。
しかし、それには代償があります。ベースイメージにセキュリティ脆弱性があると、新たに作成するイメージにも引き継がれます。多数の脆弱性を含む大きなベースイメージを選び、最初から不利な状態にする必要があるでしょうか?
ベースイメージのセキュリティ脆弱性の多くは、そのイメージが使用するOSレイヤーに由来します。Snykの2019年の調査Dockerセキュリティを左にシフトでは、選択したディストリビューションによって、OSレイヤーに起因する脆弱性の数が大きく異なることが示されました。

これは、利用を検討しているあらゆるベースイメージに当てはまる問題です。たとえば、2020年版オープンソースセキュリティの現状レポートでは、最新のビルドを含む主要なDockerイメージを紹介しています。Dockerのベースイメージには、デフォルトで一貫してセキュリティ脆弱性が含まれていることがわかります。
2. 開発中にNode.js Dockerイメージをスキャンする
他のイメージをベースにDockerイメージを作成したり、イメージを再ビルドしたりすると、新たな脆弱性が持ち込まれる可能性があります。しかし、そのリスクを把握する方法があります。
Dockerイメージのビルドも、他の開発作業と同じように扱いましょう。自分が書いたコードをテストするのと同じように、構築したDockerイメージもテストする必要があります。
テストには、Dockerfileのセキュリティ上の落とし穴や好ましくないパターンを避けるための静的ファイルチェック(リンター)が含まれます。これらの一部をDockerイメージのセキュリティに関するベストプラクティスにまとめています。Node.jsアプリケーションの開発者は、手順を追って解説するDockerでNode.js Webアプリケーションをコンテナ化するための10のベストプラクティスもぜひご覧ください。
GitリポジトリをSnykに接続するのも効果的です。SnykはGitHub、GitLab、Bitbucket、Azure Reposとのネイティブインテグレーションに対応しています。Git連携を設定すると、プルリクエストをスキャンし、セキュリティ脆弱性が見つかった場合にその情報を注釈として追加できます。これにより、新たなセキュリティ脆弱性が持ち込まれるプルリクエストをブロックし、マージを拒否できます。
継続的インテグレーション(CI)の柔軟性を高めたい場合や、開発者エクスペリエンスに緊密に統合したい場合は、Snyk CLIをご利用ください。
CLIを使うと、Dockerコンテナイメージを簡単にテストできます。たとえば、Dockerイメージをローカルでビルドし、nodejs:notification-v99.9というタグを付けたとします。次のようにテストします。
Snyk CLIをインストールします。
$ npm install -g snyk次に、以下を実行してSnyk CLIにAPIトークンを自動取得させます。
$ snyk authローカルのベースイメージをスキャンします。
$ snyk container test nodejs:notification-v99.9
テスト結果は、CVEに関する情報や、脆弱性を持ち込んでいるパスとともに画面に表示されます。どのOS依存関係が原因なのかを確認できます。
以下は、Dockerベースイメージnode:15をテストした場合の出力例です。
Snyk CLIでできることをまとめたSnyk CLIチートシートをご用意しています。また、ドキュメントではSnyk Container CLIの利用開始方法について詳しくご覧いただけます。
3. Dockerイメージ内のNode.jsランタイムの脆弱性を修正する
Dockerコンテナイメージのリスクを管理する際、見落とされがちなのがアプリケーションのランタイムそのものです。JavaでDockerを利用する場合も、DockerでNode.js Webアプリケーションを実行する場合も、Node.jsアプリケーションのランタイム自体に脆弱性が存在する可能性があります。
Node.jsのセキュリティリリースとNode.jsのセキュリティポリシーを把握し、それに従う必要があります。手動で情報を追い続ける代わりに、Snykを活用してNode.jsのセキュリティ脆弱性も検出しましょう。
さまざまなNode.jsベースイメージのタグに含まれるセキュリティ脆弱性の状況を把握するため、いくつかのタグをSnyk CLIでスキャンし、結果を次の対数スケールのグラフにまとめました。

次のことがわかります。
デフォルトの
nodeベースイメージタグ(node:latestというタグも付いています)には、500件を超えるセキュリティ脆弱性が含まれています。さらに、Node.jsランタイム自体にも2件のセキュリティ脆弱性が持ち込まれます。本番環境でNode.js 15を実行していて、パッチ適用や修正を行っていない場合は、注意が必要です。node:alpineベースイメージタグには、脆弱なOS依存関係が含まれていない可能性があります。そのため青いバーは表示されていませんが、最新のNode.jsランタイム(バージョン15)の脆弱なバージョンが含まれています。たとえばNode.js 10など、サポート対象外のバージョンを実行している場合、そのバージョンには脆弱性があり、セキュリティアップデートも提供されません。
この記事の執筆時点で最新リリースだったNode.js 15を選ぶと、このコンテナ内にある561件のセキュリティ脆弱性に加え、Node.jsランタイム自体にある2件のセキュリティ脆弱性にもさらされることになります。
Dockerスキャンのテスト結果は、こちらの公開イメージテストURLでご覧いただけます。こちらの無料公開Dockerスキャンサービスを使って、利用中の他のNode.jsベースイメージタグもぜひテストしてください。

Dockerユーザーアカウントをお持ちの場合は、そのアカウントを使用してSnykに接続し、Docker Hubのリポジトリをすばやくインポートできます。
4. Node.jsアプリケーション用にデプロイしたDockerイメージを監視する
Dockerイメージをビルドしたら、通常はイメージを管理するDockerレジストリにプッシュします。こうすることで、イメージをデプロイし、機能するコンテナアプリケーションとして起動できます。
Dockerベースイメージを監視する必要があるのはなぜですか?
ここまで紹介した、ベースイメージのスキャンや修正に関するセキュリティガイドラインをすべて実践しているなら、すばらしいことです。ただし、新たなセキュリティ脆弱性は絶えず発見されています。現在イメージに78件のセキュリティ脆弱性があるとしても、新しいCVEが報告され、本番環境で稼働中のコンテナに影響が及べば、明日の朝には100件になっているかもしれません。コンテナのデプロイに使用しているコンテナイメージのレジストリを監視することが重要なのはそのためです。セキュリティ問題を早期に検出し、修正できるようになります。
Snykアプリから多数のDockerイメージレジストリと直接連携できます。たとえば、Docker Hub、ACR、ECR、GCR、Artifactoryからイメージをインポートすると、Snykが定期的にスキャンし、セキュリティ問題が見つかった場合はSlackやメールで通知します。

5. セキュアで最適なNode.js Dockerイメージを実現するためのセキュリティガイドラインと本番環境向けの推奨事項に従う
ここまでのセキュリティガイドラインをすべて実践されている皆さん、お疲れさまです。
最後に、Node.jsやJavaアプリケーション向けの最適なDockerイメージを構築するためのセキュリティのベストプラクティスを知りたい方は、次のリソースをご覧ください。
Dockerセキュリティのベストプラクティス10選 - Dockerベースイメージの構築時と取得時に従うべき、詳しいセキュリティ対策を紹介します。Docker Content Trustについても解説しています。
Java開発者の方には、こちらがおすすめです。Java開発者がDockerでセキュリティを損なわないために知っておくべき5つのこと
DockerでNode.js Webアプリケーションをコンテナ化するための10のベストプラクティス - Node.js開発者なら、手順を追って解説するこのガイドをぜひご活用ください。Node.jsアプリケーション向けに、安全で高性能なDockerベースイメージを構築する方法を紹介します。
Snykでコンテナイメージのテストと修正を始めましょう。
CTFを始めよう
オンデマンドのバーチャル入門ワークショップで、CTFチャレンジの解き方を学びましょう。
