Docker(コンテナ)と VM(仮想マシン)の仕組み・構成・性能を層ごとに比較します。
VM(仮想マシン)とコンテナはどちらもアプリケーションを隔離して実行する技術ですが、隔離のレベルが根本的に異なります。
アナロジーで言えば、VMは一戸建て、コンテナはマンションの一部屋です。一戸建ては基礎・壁・屋根をすべて独自に持ちますが、マンションは構造体を共有しつつ部屋単位で隔離します。
コンテナはホスト OS のカーネルを共有しながら、アプリケーションを隔離して実行する技術です。アプリと依存ライブラリだけをパッケージ化するため、OS 全体を含む VM と比べて非常に軽量です。
Linux カーネルの Namespace(プロセス・ネットワーク・ファイルシステムの隔離)と cgroup(CPU・メモリの使用量制限)という2つの仕組みで隔離を実現しています。
OS カーネルを含まないため、イメージサイズは数十〜数百 MB。起動は 1 秒未満で、プロセスを起動するのとほぼ同じ速度です。1台のサーバーで数百のコンテナを動かすことも可能です。
アプリと依存関係をイメージにまとめるため、「自分の PC では動くのにサーバーでは動かない」問題を解決します。Docker がインストールされていればどの環境でも同じように動作します。
Namespace: コンテナごとにプロセスID、ネットワーク、ファイルシステムを分離します。コンテナ A からコンテナ B のプロセスやファイルは見えません。
cgroup: コンテナごとに CPU やメモリの使用量を制限します。1つのコンテナが暴走しても、他のコンテナやホストに影響しません。
仮想マシンはハイパーバイザーという仮想化ソフトウェアを使って、1台の物理サーバー上に複数の「仮想的なコンピュータ」を作る技術です。各 VM は独自の OS カーネルを持ちます。
VM の中で動く OS はゲスト OS と呼ばれ、ホスト OS とは完全に独立しています。Linux のホスト上で Windows の VM を動かす、といったことも可能です。
各 VM は独自のカーネルを持つため、1つの VM で脆弱性が見つかっても他の VM には影響しません。クラウドプロバイダー(AWS, Azure 等)がマルチテナント環境で VM を採用する理由がこれです。
コンテナはホストと同じカーネルしか使えませんが、VM なら Linux ホスト上で Windows を動かしたり、異なるバージョンの Linux を並行して走らせることができます。
Type 1(ベアメタル型): ハードウェア上で直接動作。VMware ESXi, AWS Nitro, KVM など。本番環境で使われる。
Type 2(ホスト型): OS 上のアプリとして動作。VirtualBox, VMware Workstation など。開発・テスト用途で使われる。
ゲスト OS 全体を含むため、イメージサイズは数 GB〜数十 GB。起動に 30 秒〜数分かかります。1台のサーバーで動かせる VM は数十台程度で、コンテナの数百台と比べると密度が低いです。
docker run --memory=512m --cpus=2 のようなリソース制限はcgroupで実現されています。
Docker コンテナの状態遷移(create → start → running → stop → remove)をステップで可視化します

マルチコンテナ構成の起動・通信・停止の仕組みを可視化

Volume・Bind Mount・tmpfsの3方式の仕組みとコンテナ削除時のデータの行方を可視化

複数ステージで最終イメージを劇的に軽量化する仕組みを可視化

イメージのpush/pullとレイヤー単位の転送の仕組みを可視化

Dockerfileの各命令でレイヤーキャッシュがヒット/ミスする仕組みを可視化。命令の順番がビルド速度に与える影響を理解できます