Dockerのアーキテクチャとは?
Dockerのアーキテクチャは、Dockerの基盤となるすべてのコンポーネント(Dockerデーモン、Dockerクライアント、Dockerレジストリなど)とその相互接続を定義しています。
ページを下にスクロールしていただくと、Docker内部の実際の構造と動作、そしてそれを活用する様々なコンポーネントについて学んでいただけます。
Dockerコンテナのしくみについて
Dockerコンテナの基本的な考え方は、コンテナの実行が設定されたあらゆるサーバーへ移動し、実行可能な独立したソフトウェア単位であるという点です。対象となるサーバーは、ノートパソコン、EC2インスタンス、あるいはプライベートデータセンター内のベアメタルサーバーなど、多岐にわたります。
Dockerのアーキテクチャの中核をなすのはDockerデーモンであり、ユーザーに対してOS固有の詳細を抽象化するレイヤーを提供すると同時に、コンテナのライフサイクル(ビルドからインストール、実行、クリーンアップまで)のあらゆる側面を、使いやすく再現性のある方法で処理する能力をユーザーに与えます。この抽象化によってもたらされる利点により、コンテナは非常に人気を博しています。
DockerをLinux上で使用する場合でもWindows上で使用する場合でも、アプリケーションの操作を開始するために全く同じコマンドを使用できます。以下の図はDockerのアーキテクチャを示しています。

仮想化技術は、ワークロードを分離し、移動させ、必要な分だけリソースを提供できる点で普及しました。しかし、コンテナはこの機能をはるかに効率的に実現します。
仮想マシンインスタンスは、オペレーティングシステム全体をインストールし稼働させる必要があり、これにより多くのオーバーヘッドが発生します。また、開発者が構築する環境と本番環境で稼働する環境の間で管理すべき変数の数も増加します。
一方、コンテナはオペレーティングシステムの単一インスタンスのみで動作するため、同じサーバー上でより多くのインスタンスを実行できます。以下の図は、Dockerコンテナと仮想マシンの実行における違いを示しています:

Docker Engine
Docker EngineはDockerプラットフォームの中核であり、コンテナのライフサイクル全般を管理します。主に3つの構成要素から成り立っています:コマンドラインインターフェース、REST API、そして実際の処理を担当するデーモンです。
クライアント側においては、Docker CLIが依然としてDockerエコシステム内で最も広く利用されているクライアントオプションであると考えられます。アプリケーションライフサイクルのテストおよび開発段階で多用されています。近年では、特に初心者ユーザー向けに優れたユーザー体験を提供するため、REST APIを活用したグラフィカルユーザーインターフェースを備えたツールが増加傾向にあります。
これにはDocker Desktopのような公式ツールや、Visual Studio Code用Dockerプラグインのようなサードパーティ製ツールとの統合が含まれます。
CLIやAPI経由で呼び出せるコマンドの種類は、ホストネットワークの設定からコンテナのビルド、単純なコンテナの実行まで多岐にわたります。Docker Engineのもう一方の側面は、ホスト上で動作するデーモンです。このデーモンは、コンテナが使用するネットワークやストレージの管理など、OS固有のコマンドをすべて処理します。
実際のランタイム層では、デーモンはコンテナランタイムを活用します。このランタイムは、ホストオペレーティングシステムとの連携方法を知っており、実際のコンテナインスタンスの展開、セキュリティおよびクォータポリシーの適用、起動、停止、クリーンアップを行います。
Docker Engine が使用するデフォルトのコンテナランタイムは containerd ですが、特定のシナリオに基づいて他のオプションを好むユーザーもいます。
Docker レジストリ
コンテナの大きな利点の一つは、サーバー間で移動可能であることです。Docker レジストリは、まさにこの要件を実現するために Docker が提供する、セルフマネージドのオープンソースソリューションです。コンテナレジストリは、コンテナイメージがビルドされた後に個々のイメージを保存するだけでなく、関連するメタデータ(バージョン、タグ、作成日時、作成者、さらにはセキュリティスキャン結果など)も保存します。
クラウド上で動作するマネージドサービスとしては、DockerはDocker Hubを提供しています(ベンダーやコミュニティから提供された数千もの事前ビルド済みイメージが利用可能です)。
Docker RegistryまたはDocker Hubを使用する際の一般的なワークフローは、Docker Engineを用いて以下の手順を実行することです
- コンテナイメージをビルドします。
- ビルドマシンから選択したレジストリへイメージをプッシュします。
- 消費マシン上で使用したい正確なイメージをプルするようDockerに指示します。
- そして最後にイメージを実行します。
Dockerオブジェクト
Dockerイメージ
Dockerのビルドプロセスにより、Dockerイメージが生成されます。これはレジストリとの間で移動されるバイナリであり、ベースとして使用され(他のコンテナイメージを構築するための基盤となります)、コンテナランタイムエンジンによって実際の稼働コンテナインスタンスを構築するために使用されます。
Dockerイメージはレイヤー構造で構築されます。各レイヤーは前層の内容を拡張し、最終的にコンテナに追加される段階でアプリケーションが要求する全ての依存関係を充足するよう設計されています。
このレイヤー構造により、開発者は自身の専門領域に集中でき、Dockerイメージの転送効率が向上します。また、アプリケーションの基盤として利用可能なイメージの在庫を整備することで、開発者の時間を節約できます。
例えば、組織では、コアライブラリとアプリケーションポートフォリオ全体で共通して使用される証明書を含むコンテナベースイメージを標準化できます。次のステップとして、そのベースイメージを最初のレイヤーとして使用し、Java、Go、Node用の第二レイヤーを作成します。開発者はその言語固有のインスタンスを利用します。
これにより、重大なCVEやその他の欠陥に対してはベースイメージまたは言語レイヤーを更新しつつ、開発者は自身のビルドに含めるバージョンへの参照を変更するだけで、都合の良いタイミングで更新が可能となります。
レイヤー方式の追加的な利点として、各レイヤーはレジストリへのアップロードやホストマシンへのダウンロードが、既に存在しない場合にのみ行われます。
したがって、組織がホスト上でNodeを実行する10個のコンテナ化アプリケーションを運用している場合、ベースイメージレイヤーとNodeレイヤーの両方とも、それぞれ1コピーのみが存在することになります。これにより、ダウンロード時間を大幅に節約できるだけでなく、必要なディスク容量も削減できます。
Dockerコンテナインスタンス
Dockerイメージがホストにダウンロードされ起動されると、実行中のコピーはコンテナインスタンスと呼ばれます。これは次のような単一のコマンドラインで実行できます
# this will download the latest version of the nginxCode language: Shell Session (shell)
# container image from the default registry and start it
$ docker run nginx:latest
Dockerボリューム
ボリュームは、データをコンテナインスタンスの外部に書き込むことを可能にするためにDockerによって管理されます。これにより、実際のコンテナインスタンスのライフサイクルを超えてデータを永続化することが可能となります。
この機能により、コンテナは永続的なデータを扱うことが可能となり、データベースやその他のデータ駆動型アプリケーションを、データ損失を心配することなくDocker内で実行できます。ストレージドライバーは、クラウドストレージ、ネットワーク接続型ストレージ、その他の高性能ストレージサブシステムを活用しつつ、アプリケーションのニーズを支える最適なパフォーマンス特性を提供します。
Dockerネットワーク
Dockerは、コンテナのほとんどの潜在的なニーズに対応する複数のネットワークタイプをサポートしております。プラグイン可能なアーキテクチャに基づいているため、組み込みオプションが機能しない場合にはサードパーティ製オプションもご利用いただけます。
- ブリッジネットワークは、ネットワーク設定用のデフォルトプラグインです。コンテナが独自の分離されたネットワーク空間を持ち、Dockerホスト上で設定されたルーティングに基づいて相互に通信することを可能にします。
- ホストベースネットワークは、ホストオペレーティングシステムと同一のネットワークスタックを共有します。これにより、ホストと実行中のコンテナ間の分離は提供されないため、ポート競合などの問題には細心の注意を払う必要があります。
- オーバーレイネットワークは、複数のホストにまたがってスウォーム内で実行される複数のコンテナ化されたアプリケーション間において、シームレスな(そしてオプションで暗号化された)ネットワーク接続を可能にします。
- MacVLANおよびIPvlanも利用可能で、ネットワークスタックの下位層(レイヤ1およびレイヤ2レベル)へのアクセスを提供します。これは仮想マシンが提供するネットワーク機能に近く、通常はアプリケーションの特定の要件に基づいて選択されます。
- 最後に、コンテナにnoneを使用するよう指示するオプションがあります。これはコンテナインスタンス内のすべてのネットワーク機能を無効化します。
高度なDockerアーキテクチャ
Dockerオーケストレーション
コンテナオーケストレーションは、需要のピーク時や谷間に対応するためにコンテナのスケーリングを可能にする重要な機能です。また、コンテナが稼働しているノードがクラッシュした場合、新しいノード上で自動的に回復することも実現します。
本質的に、コンテナオーケストレーションとは、Kubernetesクラスター(またはDocker Swarm)内の全てのコンテナをテトリスのように配置し、定義されたパラメータ内で確実に動作させる管理活動です。
本番環境におけるDocker
Docker社(企業)は開発者向けの最良の体験提供に注力する方向へ移行し、一方でMirantis社がDockerのエンタープライズシステムを買収しました。
これは、本番環境でDockerを実行できないという意味ではありません(Dockerには依然としてSwarm機能があります)。しかし、マルチサーバーの本番環境でDockerコンテナを実行するために、業界内でより広く利用されるようになった他のソリューション(主にKubernetes)が存在します。
Dockerコンテナのスケーリングとオーケストレーション
Dockerが業界内の一貫性を確保するため標準化団体と連携する姿勢に支えられ、組織はDockerツールを最適な場面で活用してコンテナイメージを構築・テスト・公開し、その後Kubernetesとそのエコシステムの強みを活用して、それらのDockerイメージを実質的にあらゆる場所で実行することが可能となります。
遠隔地で5G無線を稼働させる3ノードクラスター上であっても、大規模なeコマース企業を支えるKubernetesクラスター内の数千ノードにまたがるアプリケーションであっても、すべてのインスタンスは開発者が構築しQAが検証した全く同一のイメージを実行しています。
