コンテナテクノロジーの理解
コンテナは、サンドボックステクノロジーの一種です。名前が示すように、サンドボックスとは、アプリケーションを「コンテナ」のようにパッケージ化し、確立された境界によってアプリケーションが互いに干渉しないようにする技術です。さらに、これらの「コンテナ」に含まれるアプリケーションは、異なるシステム環境間で移行および実行できます。コンテナテクノロジーの背後にある原理を掘り下げる前に、プロセスの概念を理解することが不可欠です。プロセスの静的な表現はプログラムであり、通常はディスク上で静かに待機しています。実行されると、コンピュータ内のデータと状態の合計、つまり動的な表現に変わります。コンテナテクノロジーの中核機能は、プロセスの動的な動作を制約および変更することによって、プロセスに「境界」を作成することです。
Docker コンテナテクノロジー
ほとんどの Linux コンテナ(Docker を含む)では、主に Cgroups テクノロジーが制約を課すために使用され、Namespace テクノロジーがプロセスビューを変更するための主要な方法です。Linux オペレーティングシステム(例:Ubuntu 22.04)上で Docker プロジェクトを実行していると想像してください。実験用にコンテナを作成しましょう。
$ docker run -it busybox /bin/sh
この Docker コマンドは、busybox イメージに基づいてコンテナを起動し、その中でインタラクティブなシェルセッションを実行します。
docker run:新しいコンテナインスタンスを作成して起動します。-i:端末が接続されていなくても STDIN を開いたままにし、コンテナとの対話を可能にします。-t:疑似端末または端末を割り当て、対話型シェル環境を作成します。/bin/sh:コンテナ起動時に実行するコマンドを指定します。この場合、コンテナ内でシェルセッションを起動します。
コンテナ内のプロセス
したがって、Ubuntu マシンがホストとなり、/bin/sh を実行するコンテナがその中で動作します。この例とその基本原理は、経験豊富な Docker ユーザーにはおなじみのはずです。コンテナ内で ps コマンドを実行すると、興味深いことに気付くでしょう。
/ # ps
PID USER TIME COMMAND
1 root 0:00 /bin/sh
10 root 0:00 ps
ここでは、Docker 内で実行されている最初の /bin/sh がコンテナ内のプロセス番号 1(PID=1)であり、2 つのプロセスだけが実行されています。これは、/bin/sh と実行したばかりの ps コマンドが、ホストとは異なる独立した環境に隔離されていることを意味します。
Namespace メカニズム
これはどのように達成されるのでしょうか?通常、/bin/sh プログラムがホスト上で実行されると、オペレーティングシステムは一意に識別するためにプロセス ID(例:PID=100)を割り当てます。このプログラムを Docker コンテナ内で実行する場合、Docker は「錯覚」を適用し、実際には PID=100 であるプロセスが自分自身を最初のプロセス(PID=1)であると認識させます。このメカニズムは、隔離されたアプリケーションのプロセス空間を操作し、再計算されたプロセス ID を認識できるようにします。
Linux の Namespace テクノロジー
Namespaces の使用は非常に興味深いものです。これは Linux で新しいプロセスを作成するための単なるオプションパラメータです。Linux でプロセスを作成するシステムコールは clone() で、次のようになります。
int pid = clone(main_function, stack_size, SIGCHLD, NULL);
この呼び出しは新しいプロセスを作成し、そのプロセス ID である pid を返します。clone() システムコールを使用して新しいプロセスを作成するときに、CLONE_NEWPID 引数を指定できます。
int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL);
その後、新しく作成されたプロセスは、新しいプロセス空間を「認識」し、その中で PID が 1 になります。この「錯覚」はホストのプロセス空間での実際の PID(例えば 100)を変更するものではなく、実際の値のままです。
複数の Namespace の動作
上記の clone() 呼び出しを繰り返し実行すると、複数の PID Namespace が作成されます。各 Namespace のアプリケーションプロセスは、自分自身がそれぞれのコンテナ内の最初のプロセスであると信じており、ホストの実際のプロセス空間や他の PID Namespace の詳細を認識しません。PID Namespace の他に、Linux は Mount、UTS、IPC、Network、User Namespace を提供し、さまざまなプロセスコンテキストを「隠蔽」します。
Mount Namespace
- Mount Namespace:隔離されたプロセスが現在の Namespace に関連するマウントポイントのみを認識できるようにします。つまり、コンテナ内のプロセスはホスト上の他のマウントポイントを認識しません。
Network Namespace
- Network Namespace:隔離されたプロセスに、現在の Namespace 固有のネットワークデバイスと構成のビューを提供します。各 Network Namespace は、独自のネットワークデバイス、IP アドレス、ルーティングテーブル、ポート番号を持ち、ホストや他の Namespace から分離されています。
その他の Namespace
- UTS Namespace:ノード名(ホスト名)とネットワークホスト名情報を隔離します。
- IPC Namespace:プロセス間通信(メッセージキューやセマフォなど)のためのリソースを分離します。
- User Namespace:ユーザー ID とグループ ID を隔離し、コンテナ内のユーザー ID をホスト上の異なる ID にマッピングして、セキュリティを強化します。
Docker コンテナの実装原理
これが Linux コンテナの基本的な実装原理です。したがって、一見複雑に見える Docker コンテナの概念は、基本的にはコンテナプロセスを作成するときに一連の Namespace パラメータを指定することです。その結果、コンテナは現在の Namespace によって制限されたリソース、ファイル、デバイス、状態、または構成のみを「認識」でき、ホストや関連のないプログラムを完全に認識しません。
コンテナと仮想マシンの比較
したがって、コンテナは特別な種類のプロセスです。プロセスに独立した空間を割り当てるというアイデアを考えると、仮想マシンが思い浮かびます。仮想マシンは、Hypervisor ソフトウェアを通じてハードウェアをシミュレートし、完全なゲストオペレーティングシステムを実行してアプリケーションの隔離を実現します。対照的に、Docker コンテナは Namespace と Cgroups テクノロジーを通じて隔離を実現しながら、ホストのオペレーティングシステムカーネルを共有します。
Docker の軽量仮想化
Docker は「軽量」仮想化テクノロジーと呼ばれることがよくあります。これは、ハードウェアシミュレーションや追加のオペレーティングシステムの実行を必要とせずに、ホストリソースを直接活用するためです。これにより、起動速度、リソース使用率、パフォーマンスの点で、従来の仮想マシンに比べて大きな利点があります。
結論
Docker コンテナテクノロジーは、Namespace と Cgroups テクノロジーを通じて、アプリケーションプロセスに隔離されながらも軽量な環境を提供します。このテクノロジーにより、コンテナは迅速に起動し、効率的に実行され、ホストや他のコンテナとの隔離を維持できるため、最新のクラウドコンピューティングやマイクロサービスアーキテクチャにおいて不可欠なテクノロジーとなっています。
Novita AI、無限のクリエイティビティのためのワンストッププラットフォーム。100 以上の API にアクセスできます。画像生成から言語処理、オーディオ強化、ビデオ操作まで、従量課金制で安価です。GPU メンテナンスの手間から解放され、独自の製品を構築できます。無料でお試しください。
