Dockerコンテナ:
オープンソース ライセンスの考慮事項は何か

Linux Foundationが今回発行したホワイトペーパーは、Dockerコンテナを配布・デプロイする際に生じるオープンソース ライセンスが及ぼす複雑な影響を明らかにすることを目的としています。

はじめに

ソフトウェア、特にサービスをデプロイ、配布、および実行する方法は、ここ数年で大きく変化しています。数年前は、必要な他のソフトウェアやディペンデンシー(依存関係のあるもの)をLinuxディストリビューションと一緒にインストールする必要がありましたが、最近では、「Dockerコンテナをスピンアップ (Spin up)」してサービスを実行することがより一般的になっています。

コンテナは基本的に、単一の独立した実行環境で、すべてのディペンデンシー、データ、および構成情報を備えたアプリケーションで、新しいシステムを購入したり、仮想マシンを作成したりすることなく、実行環境をデプロイできます。コンテナを使用すると、サービスの実行環境を互いに独立させて提供でき、かつ仮想マシンと比較してはるかに少ないリソースでそれを実現できます。そこで、Amazon Web Services(AWS)、Microsoft Azure、Google Cloudなどのようなハイパースケール クラウドプロバイダーによって提供される、非常に高密度のマルチテナント ホスティング環境で大変人気が高まっています。

Dockerはコンテナの普及に非常に大きな影響を与えました。技術的な面では、コンテナの利用方法を大きく単純化しました。しかし、法的な面では、煩雑さが増す可能性があります。たとえば、コンテナを使用すると、開発者がソフトウェアをデプロイしやすくなりますが、(ときには不注意で)間違ったものをデプロイしやすくなります。Dockerコンテナは開発者が実装の詳細を知らなくてよいようしてくれています。しかし、結果として、これにより、開発者はライセンスコンプライアンス問題が発生することも知らずに、各種ソフトウェアを無意識のうちに出荷してしまう可能性があります。

Linux Foundationは最近、Dockerコンテナをデプロイする際のオープンソース ライセンスの影響の複雑さを明らかにすることを目的としたArmijn Hemelによるホワイトペーパーを公開しました。こちらからダウンロードできます(英語)。そのサマリーを本ブログで紹介します。

コンテナとイメージ:違いは何か

Dockerに関する記事やドキュメントでは、「コンテナ」や「イメージ」について頻繁に言及しています。これらは同じではありませんが、記事や会話では同じ意味で使用されることがしばしばあります。しかし、両者には根本的な違いがあります。イメージはディスク上のソフトウェアの集合体であり、コンテナはイメージの実行中のインスタンスであり、ランタイム データとランタイム ステートを含むものです。

サンプルのイメージは、Apache webサーバーとすべてのディペンデンシーを含むことができ、そのイメージをインスタンス化し、コンテナとして実行できます。イメージは複数のコンテナとしてインスタンス化でき、それらはすべて異なった別のコンテナになります。

図1.  1つのDockerイメージが複数のコンテナにインスタンス化される

イメージは、パブリック リポジトリやプライベート リポジトリに格納でき、検索したり、ダウンロードして再利用したりできるようになります。

各Dockerイメージは、互いに積み重ねられた1つまたは複数のレイヤーで構成されます。一部のレイヤーはファイル(プログラム、ファイルなど)が含まれています。他のレイヤーは、既存のレイヤーの変更情報を持つメタレイヤーです。また、異なったイメージ間でレイヤーを共有することもできます。たとえば、2つのイメージがどちらも同じ特定のDebianレイヤーをベースにしている場合、このDebianレイヤーはディスクに1つだけ保存されます。

既存のイメージが再利用され(たとえば、リポジトリからダウンロードされ)、変更が加わると、これらの変更はイメージ内の既存のレイヤーの上に1つ以上の個別のレイヤーとして保存されます。ベース イメージのすべてのレイヤーと変更された新しいレイヤーが一緒になって新しいイメージを形成し、インスタンス化されたり(コンテナを作成するために)、配布やリポジトリでの利用のためにエクスポートされたりできるようになります。Dockerイメージは、たとえば次の図のようになります。たとえば、4つのベース レイヤー(スタック構成で構築されている)を持つベース イメージと、その上のカスタムレイヤーで構成されています。

図2.  4つのベース レイヤーとその上にカスタム レイヤーを持つベース イメージ

コンテナ内のレイヤーのライセンスの複雑さを理解する

Dockerイメージ内に存在するソフトウェアのライセンスが与える影響を理解するには、「ユーザーが使用しているイメージはすべてのレイヤーのビューに過ぎず、実行時には最終的なビューしか見えない」ことを認識することが重要です。このビューは、すべてのレイヤー内のすべてのソフトウェアを表示しない可能性があるということです。すなわち、各レイヤーはビューを変更できますが、基礎となっているレイヤーに格納されているコンテンツは変更しません。

 

図3.  Dockerイメージの合成図

あるレイヤーがソフトウェアをインストールし、新しいレイヤーがそのソフトウェアを別のバージョンで(おそらく異なったライセンスの別バージョンで)上書きする可能性があります。最終的なビューでは、古いソフトウェアが削除されたように見えますが、ベースとなっているレイヤーには上書きされる前の元のソフトウェアがまだ存在しています。たとえば、上記のコンテナ イメージでは、このイメージのユーザーは以下に示すものだけを「見る」ことになります。

図4. エンドユーザーによるコンテナ イメージ

ただし、イメージが配布される時には、すべてのレイヤーのすべてのファイルが配布されます。AからHのそれぞれと、変更されたファイルB’およびC’も配布されます。

完全なイメージが送付された場合は、最終的なビューで一部のレイヤーのソフトウェアが表示されていなくても、すべてのレイヤーのソフトウェアのライセンス条件が適用されます。つまり、イメージ全体をライセンスに準拠させるために、イメージ内のすべてのレイヤーのライセンス状況をチェックする必要があります。

さらに複雑なのがリンクがあることです。コンポーネントがあるレイヤーの他のコンポーネントとリンクされており、コンポーネントが別のライセンスで提供されている他のバージョンで上書きされると、どのレイヤーを調べるかによってライセンスの意味合いが異なる場合があります。

Dockerのリポジトリ、レジストリ、そしてライセンスの誤解釈の可能性

Dockerイメージはリポジトリから取得できます。Dockerが運営するdocker.ioリポジトリのほかにも、Red Hatが運営するquay.ioなどのリポジトリがあります。FedoraやCentOSなどのコミュニティ プロジェクトにもパブリック リポジトリがあり、Dockerイメージのプライベート リポジトリを運営しているところもたくさんあります。

リポジトリから完全なイメージを取得する方法に加えて、Dockerは「ジャストインタイム」方式でイメージを構築することができます。この方式では(完全なディスク イメージやコンテナ イメージが提供されるのではなく)Dockerfileを使用してコンテナ イメージを組み立てるための「レシピ」のみが提供されます。

ソフトウェアは、リポジトリからダウンロードされたベース イメージや、ローカルシステム上で使用可能なベースイメージから、実行時に動的に作成されます。それらは、Linuxディストリビューションからのアップデートのインストールのように、他の追加のソフトウェアもアップストリームからインストールされている可能性があります。

例は、ベースイメージがUbuntu Linuxの特定のバージョンに基づいており、アップデートはUbuntuアップデート サーバーから送信され、次にローカル サーバーからプロプライエタリのプログラムがインストールされることを定義するレシピです。

Dockerfileなどのレシピは、スタック化して他のレシピファイルとディペンデンシーを持たせることが可能です。これらのレシピファイルは通常、検索可能なローカルファイルやレジストリに保存されます。

イメージの組み立てに使われているレシピは、実際に集約されるソフトウェアとは異なるライセンスでリリースされていることがあります。このこと自体はまったく問題ありません。また、人々がこの情報を誤って解釈し、組み立てられたイメージにDockerfileファイルのライセンスが適用されると考える可能性がありますが、これは正しくありません。

コンテナ イメージで生じる可能性のあるライセンスに対する誤解釈は、非現実的な問題ではありません。コンテナ化されたコンテキストではありませんが、過去にAndroidで、実際に同様のことが起こり、Androidの大部分がApache 2でリリースされていたためです。このライセンスの混乱により、一部の人々は、Androidのかなりの部分がGPL-2.0(Linuxカーネル、iptablesなど)やさまざまなバージョンのLGPLライセンスでリリースされていたにもかかわらず、AndroidのすべてがApache 2でリリースされていると信じるようになりました。

誰がソフトウェアを配布しているのか

コンプライアンスの観点からは、すでに完全に作成されているイメージ(そしてすべてのソフトウェアがそのイメージに含まれている)の配布と、イメージの作成方法のみを記述したDockerfileの配布には大きな違いがあります。前者の場合、ソフトウェアはバイナリ形式で配布されますが、後者の場合、イメージを作成するためのレシピのみが配布される可能性もあります。

完成したイメージが配布される際は、1つのパーティーだけがそのイメージ配布を実行します。つまり、ビルドされたイメージはそのパーティーからのみ送信されています。しかし、Dockerfile(レシピ)が配布される場合は、エンドユーザーが実行時にイメージをビルドする時に、さまざまな場所からソフトウェアが持ってこられる可能性があります。このシナリオでは、配布は複数のパーティによって行われる可能性があることを意味します。なぜなら、(たとえば)各レイヤーは異なるサードパーティから送られてくる可能性があるからです。あるレイヤーは、イメージ リポジトリを運用するパーティーによって配布され、別のレイヤーのコンテンツはディストリビューションから(ディストリビューション アップデートなどで)、そして別のレイヤーのコンテンツはさらに別のパーティー(カスタム ダウンロード サーバー)から配布されるかもしれません。

Dockerfilesのライセンスとコンテナ内のソフトウェアのライセンス

Dockerfileファイルは、それ自体をオープンソース ライセンスのもとでライセンスすることができます。このライセンス ステートメントの範囲はDockerfileのみであり、コンテナ イメージは含まれていないことを理解することが重要です。

たとえば、Dockerfile自体はMITライセンスに基づいてライセンスできますが、DockerfileはGPLライセンスソフトウェアのインストールを記述しているかもしれません。典型的な使用例では、Dockerfileのライセンスとそこで記述されるソフトウェアのライセンスは完全に独立したものです。

最終レイヤーだけでなく、すべてのレイヤーのコンプライアンス

イメージを配布する場合、通常、複数のレイヤーが含まれたものが配布されます。これらのレイヤーは積み重ねられているため、あるレイヤーのコンテンツが他のレイヤーのコンテンツを見えないようにしている可能性があります。純粋なライセンスの観点からは、最終的なビューは重要ではありません。重要なのは配布されるものです。あるオープンソース ライセンスのもとで、あるバージョンのプログラムが、あるレイヤーで配布され、また別バージョンの同じプログラムが別レイヤーで配布されることがあります。この場合は、両方のバージョンのライセンス条件を満たす必要があります。

また、安全のためには、イメージの特定のレイヤーが、送付先や、プッシュを受け取るリポジトリにすでに存在していると想定してはいけません。すなわち、そのような想定で、それらのレイヤーのソフトウェアを配布してはいけません。既存のレイヤーがまったく存在しないところにコンテナが配置されることもあるでしょう。この場合は、イメージのすべてのレイヤーが受信者に提供される必要があり、提供される各レイヤーの配布義務を遵守する必要があります。

必要なソースコードを収集して公開するにはどうすればよいか

未解決の問題は、「完全かつ対応するソースコードを要求するライセンスのもとに提供される当該ソフトウェアを含むコンテナの完全かつ対応するソースコードをどのように収集するのか」です。現在のDockerインフラストラクチャでは、必要なソースコードを自動的に収集して公開することはできません。つまり、適切なソースコードを収集して保存し、利用できるようにするためには、追加の作業(手動またはスクリプト)が必要になります。以下のような複雑な作業があります。

  1. Dockerイメージは、構成に依存して生成されるので再現性可能とはいえません。Dockerイメージが作成されるたびに異なる構成オプションが選択される場合、結果のイメージは異なるでしょう。すなわち、イメージを作成した後でソースコードを収集しても、作成されたイメージに対応するソースコードが生成されない可能性があります。
  2. レイヤーは異なった時期に構成されることがあり、一部のレイヤーのソースコードが消えている場合があります。
  3. さまざまな場所からソースコードを収集する必要があるかもしれません。システム パッケージのみに注目していると、パッケージの全体像を間違って判断することがあります。
  4. ソースコードの収集は、すべてのレイヤーで行う必要があります。

これは現在も解決されていない問題です。

Dockerライセンス コンプライアンスのためのチェックリスト

次のセクションは、コンテナを配布する企業がライセンスの義務をより良く理解するのに役立つコンプライアンス チェックリストです。

ソフトウェアを配布しているか

最初の質問は、「そもそもソフトウェアを配布していますか」です。配布されるものがユーザー自身でインスタンス化する必要があるDockerfileレシピのみであり、ソフトウェアはリポジトリからプルされ、Dockerfileを公開している企業がリポジトリを実行せず、Dockerfileで使用されている(ベースの)イメージをプッシュしない場合、その企業は、Dockerfile以外のソフトウェアを一切配布していない可能性が高いです。これを確認するためには、使用されているDockerfileファイルとイメージのビルドプロセスを徹底的に調査する必要があります。

どのようなソフトウェアを配布しているか

出荷されるソフトウェアと、そのソフトウェアが適用されるライセンスを知るためには、ユーザーに提供される最終的に作成されたレイヤーだけでなく、コンテナ イメージのすべてのレイヤーのソフトウェアを分析する必要があります。ソフトウェアには最終レイヤーでは見えていないものがある可能性があるため、すべてのレイヤーについて完全な分析が必要です。

ソフトウェアをどのように配布しているか

ソフトウェアの配布方法(完全なイメージ、Dockerfileを配布など)に応じて、ライセンス義務を履行する責任を負う当事者が異なる場合があります。

誰がソフトウェアを配布しているか

コンテナを全体として配布する場合は、コンテナに含まれるすべてのソフトウェアのライセンス コンプライアンスに責任があります。反面、コンテナの構築方法をユーザーに通知するDockerfileのみを配布していて、受信者がDockerfileを使用してサードパーティからコンテナ レイヤーを取得している場合は、多分、そのソフトウェアのライセンス コンプライアンスについてあなたは責任を負うことはないでしょう。

結論

Dockerはソフトウェアの高速デプロイを大幅に簡略化しましたが、いくつかの法的課題ももたらしました。これらの法的課題のいくつかについては明確な解決策を現時点では提示できません。

コンプライアンスの課題を評価するには、コンテナの機能と構築方法の技術的詳細に対する基本的な理解が必要です。これを理解すれば、コンテナの配布が、従来のソフトウェア配布方法とどのように類似しているかが明らかになりますが、不明瞭になっている面も明らかになります。

本ホワイトペーパーは、解決策を議論する出発点になると思われますが、以下のような課題も特定されました。

  1. 配布にはさまざまなタイプがあり、配布形式に応じて、対応するソースコードを配布する義務がある場合と、ない場合があります。配布義務が存在するのかどうか、何時その義務が発生するのかは、Dockerを利用しているだけの一般ユーザーはまだ明確に知ることはできません。
  2. Dockerツールとそのエコシステムは現在、完全かつ対応するソースコードを収集することが簡単にできるようにはしていません。純粋にコンテナイメージの組み立てとコンテナのデプロイに集中しています。
  3. Dockerのレイヤード アプローチと最終レイヤーのみを可視化する機能のために、ソフトウェア配布の可能性を見落としがちです。そこで、Ternなどのツールを使用して、何が配布されているかを詳細に分析する必要があります。

コンテナのコンプライアンス環境を改善するために、今後は対応するソースコードを自動的に収集し、公開できるようにするツールとプロセスの開発に焦点を当てるべきでしょう。

このホワイトペーパー “Docker Containers for Legal Professionals (法務担当者向けDockerコンテナ)”(英語)をダウンロードするには、下のボタンをクリックしてください。

The Linux Foundation
Follow Us