🐳

Dockerコンテナの内部構造

Linuxネームスペースからmacos対応、GPUまで — 10年間の技術的進化

Dockerが解決した根本問題はシンプルだ。同じマシンで異なるライブラリバージョンを要求するアプリを同時に実行すること。

VMで解決できるが、カーネル・ファイルシステム・キャッシュが全部重複して重い。DockerはLinuxネームスペースを使ってVM無しで分離を実現した。

ネームスペース — コアメカニズム

ネームスペースはプロセスごとにファイルシステム、ネットワーク、PIDなどシステムリソースの「ビュー」を分離するカーネル機能。2つのプロセスが同じ/etc/passwdを要求しても実際には異なるファイルを見る。

2001年のマウントネームスペースから2007年のネットワークネームスペースまで、合計7種類が段階的に追加された。Dockerの貢献はこれらの低レベル機能を開発者が使える形にパッケージングしたこと。

イメージ — レイヤードファイルシステム

docker buildはDockerfileの各命令を実行し、結果のファイルシステム差分をレイヤーとして積み重ねる。コンテンツアドレッサブルストレージに保存されるため、同一レイヤーは重複保存しない。

overlayfs、btrfs、ZFSなどのcopy-on-writeファイルシステム上で動作。

コンテナ実行 — containerdの役割

docker run呼び出し時にcontainerdがネームスペースを動的に設定する:

cgroups — CPU・メモリ等のリソース制限
ネットワークネームスペース — コンテナ内部ポートをホストポートにリマップ
ストレージボリューム — ホストファイルシステムの永続ストレージを接続
PIDネームスペース — プロセスツリーの分離
ユーザーネームスペース — コンテナ内UIDをホストの別UIDにマッピング

ネームスペース構成にわずかなオーバーヘッドがあるが、VMスポーンよりはるかに軽い。ほとんどのコンテナは1秒未満で起動する。

macOS対応 — 逆転の発想アーキテクチャ

DockerイメージはLinuxカーネルでしか動作しない。macOS/Windows開発者のためにDockerはハイパーバイザーをアプリ内部に組み込む方式を採用した。

HyperKit — Intel CPUのハードウェア仮想化拡張を利用して通常のユーザープロセスでLinuxカーネルを実行するライブラリVMM。ユニカーネル研究から着想を得た。

LinuxKit — Docker実行に必要な最小コンポーネントのみ含むカスタムLinuxディストリビューション。全コンポーネントがコンテナ内で実行され、ブート時のルートネームスペースでは何も動かない。

HyperKit + LinuxKitの組み合わせでネイティブmacOSプロセスとほぼ同速でLinuxプロセスをブート可能。

ネットワーキング — SLIRPソリューション

組み込みLinuxからmacOSへのネットワーキングが予想外に難しかった。企業ファイアウォールがコンテナトラフィックを悪意あるものとして検出し、ベータで数千件のバグレポートが殺到した。

解決策が面白い。1990年代にPalm Pilotをインターネットに接続するために使われたSLIRPを再利用した。OCamlで書かれたユーザースペースTCP/IPスタック(vpnkit)がLinuxネットワーキングリクエストをmacOSネイティブソケットコールに変換する。

VPNポリシーの観点からは送信トラフィックがDockerアプリから発生したものとして認識され、ファイアウォール問題が解消。vpnkit展開後、企業ユーザーのバグレポートが99%以上減少した。

GPU対応 — CDI

AIワークロードの台頭でGPU依存性管理が新たな課題に。GPUワークロードは正確に一致するカーネルドライバとユーザースペースライブラリが必要だが、コンテナは単一カーネルを共有する — Dockerが元々解決しようとしたのと同じ根本的な衝突。

2023年からCDI(Container Device Interface)をサポート。コンテナ起動時にGPUデバイスファイルと専用ダイナミックライブラリをバインドマウントする方式。同じGPUベンダー内では移植性が保証されるが、Nvidia GPU用アプリがApple Mシリーズで動くのはまだ先の話。

動作フロー

1

Dockerfile作成 → docker buildでレイヤードファイルシステムイメージ生成

2

docker run呼び出し → containerdがネームスペース(mount, network, PID, user)を動的設定

3

cgroupsでCPU・メモリリソース制限、ボリュームマウントで永続ストレージ接続

4

macOS/Windows: HyperKit(ライブラリVMM)+ LinuxKit(最小Linux)がアプリ内部でLinuxカーネル実行

5

vpnkit(SLIRP)がLinuxネットワーキングをホストOSソケットコールに変換 → ファイアウォール問題解決

6

コンテナ終了時にLinuxカーネルが通常プロセスと同様にガベージコレクション

メリット

  • VMに比べ極めて軽量 — ほとんど1秒未満で起動
  • レイヤードイメージで効率的な重複排除とビルドキャッシング
  • OCI標準でベンダーロックインなく様々なランタイムで実行可能
  • macOS/WindowsでもLinuxコンテナが「そのまま動作」

デメリット

  • GPUワークロードでベンダー間の移植性が不足
  • macOS/Windowsでは内部的にVMが動くため純粋なLinux比でオーバーヘッドあり
  • AI時代にイメージサイズが指数的に増大中 — torchだけで数GB
  • ネームスペース分離はVMレベルのセキュリティ分離ではない

ユースケース

開発環境統一 — 「自分のPCでは動く」問題を解決 CI/CDパイプライン — ビルド・テスト・デプロイを同一イメージで マイクロサービス — サービスごとの独立デプロイとスケーリング AI/MLワークロード — GPU依存性を含む環境パッケージング