🖥️

【3-1.5】「LXCとDockerの違い」をさらに深掘り!仮想化の仕組みからプロセスまで徹底解説

に公開

はじめに

前回の記事では、LXCとDockerの基本的な違いが「システムコンテナ」と「アプリケーションコンテナ」という観点から解説しました。
https://zenn.dev/koikoi_infra/articles/4b5045ddaa1b1a
本記事は、この記事の内容をさらに一歩進めて、「では、なぜそのような違いが生まれるのか?」という根本的な部分に焦点を当てます。具体的には、

といった、技術の根幹に関わる部分を、これまでの対話形式での解説を元に、できるだけ平易な言葉でまとめていきます。元記事と合わせてお読みいただくことで、コンテナ技術への理解がより立体的になることを目指します。

核心の違い:コンテナは「何を仮想化」しているのか?

VM(仮想マシン)、LXC、Docker。これらはすべて「仮想化」技術ですが、仮想化している対象が根本的に異なります。

VM vs コンテナ:仮想化レイヤーの違い

  • VM (仮想マシン): VMwareやVirtualBoxのように、CPU・メモリ・ディスクといった「ハードウェア」そのものをソフトウェアで模倣します。そのため、各VMは独立したOS(ゲストOS)を丸ごとインストールする必要があります。
  • コンテナ (LXC/Docker): ハードウェアは仮想化せず、ホストOSの 「カーネル(OSの心臓部)」を直接共有します。そのためゲストOSは不要です。その上で、ホストOSが持つ「OSのリソース」を仮想化(より正確には隔離・分割)することで、独立した環境を作り出します。

では、コンテナが隔離している「OSのリソース」とは具体的に何でしょうか?それを実現しているのが、Linuxカーネルの2大機能です。

  1. Namespaces (名前空間):「見えない壁」を作る技術
    コンテナごとに「自分だけの世界」があるかのように見せかける技術です。これにより、他のコンテナやホストOSの状況が見えなくなり、干渉もできなくなります。

    • PID Namespace: プロセスIDを隔離し、コンテナ内では自分のプロセスがPID 1に見えるようにします。
    • Network Namespace: ネットワーク環境(IPアドレスなど)を隔離します。
    • Mount Namespace: ファイルシステムを隔離し、自分だけのルートディレクトリがあるように見せます。
  2. cgroups (コントロールグループ):「リソースの割り当て」を決める技術
    各コンテナが使用できる物理リソース(CPUやメモリ)の上限を設定する技術です。「このコンテナはCPUを20%までしか使えない」といった制限をかけることができます。

「カーネルを共有する」の本当の意味

コンテナの説明で必ず出てくる「カーネルを共有する」という言葉。これは「ホストOSを共有する」とは少し意味が違います。

OSは、大きく分けて2つの要素で構成されています。

  • カーネル (Kernel): OSの「心臓部」。ハードウェア管理など、最も根幹的な部分を担当します。UbuntuやCentOSなど、多くのLinuxディストリビューションは**同じ「Linuxカーネル」**をエンジンとして使っています。
  • ユーザーランド (Userland): カーネル以外の部分すべて。コマンドやライブラリ、設定ファイルなど、私たちが普段「OSの違い」として認識している部分です。

「カーネルを共有する」とは、まさにこのホストOSが持つ「カーネル(エンジン)」を、全てのコンテナが共通で利用することを意味します。そして、その共有されたカーネルの上で、コンテナごとに独立した「ユーザーランド(ボディや内装)」を動かすのです。

これにより、Ubuntuホスト上でCentOSのコンテナを動かす、といったことが可能になります。エンジンが同じLinuxカーネルだからです。

逆に言えば、カーネルの壁は越えられません。Linuxカーネル上でWindowsアプリケーション(.exe)を直接動かすことはできないのです。
(Windows上でLinuxコンテナが動くのは、WSL2という軽量なLinux VMを介してLinuxカーネルを利用しているためです)

コンテナの中身を覗く:プロセス、プログラム、ライブラリの関係

元記事で解説されている「システムコンテナ」(LXC)と「アプリケーションコンテナ」(Docker)の本質的な違いは、コンテナの中で最初に何が動き出すかという点に集約されます。

この「動き出す実体」の違いを正確に理解するために、まずは「プログラム」「ライブラリ」「プロセス」といった、コンピュータの動作の基本となる用語を整理してみましょう。

  • プログラム: ディスクに保存されている「指示書」(例: chrome.exeファイル)。まだ動いていない静的な状態。
  • ライブラリ: プログラムを作るための便利な「部品・道具箱」(例: .dllファイル)。単体では動かせない。
  • プロセス: プログラムが実行され、メモリ上に読み込まれた「実行中の実体」。OSが管理する「作業部屋」のようなもの。

アプリケーションは、司令塔となるメインプログラムと、専門機能を持つ多数のライブラリ(部品) で構成されています。

そして「プロセス」とは、このメインプログラムと、そこから呼び出されたライブラリ群が、OSから与えられたメモリ空間(作業部屋)の中で一体となって活動している状態全体を指します。

この知識を元に、LXCとDockerをもう一度見てみましょう。

  • LXC (システムコンテナ)

    • 最初にinitという「OSの親玉プロセス」が起動します。
    • このinitプロセスが、SSHサーバーや各種サービスなど、OSとして必要な多数の子プロセスを起動・管理します。
    • まさに、OS環境一式が入った 「厨房」そのものを立ち上げるイメージです。
  • Docker (アプリケーションコンテナ)

    • initは起動せず、Webサーバーなど、動かしたいアプリケーションのプロセスが直接一つだけ起動します。
    • このプロセスは、目的のアプリケーションを動かすためだけのメインプログラムとライブラリを含んでいます。
    • 特定の料理を作るためだけの「専用の調理台」を用意するイメージです。

まとめ

前回の記事で示された「システムコンテナ vs アプリケーションコンテナ」という違いは、その背景にある

といった、技術的な思想の違いに根差しています。

コンテナ技術は、単に便利なツールというだけでなく、OSやプログラムがどのように動いているのかというコンピュータサイエンスの基礎に触れることができる、非常に興味深い分野です。この記事が、皆さんのコンテナ技術への理解をさらに深める一助となれば幸いです。

Discussion