
2026/10/23 8:45
Docker は変だ
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
本文は、主に Linux コンテナが特定のコア機能を利用して孤立化されたプロセスであり、仮想マシンとは異なること、また Docker がイメージをフォルダとして管理することを明確にしています。完全な仮想化と異なり、コンテナは隔離にはネームスペースを用い、リソース管理には cgroups を用いて、管理されたディレクトリ内でバイナリを直接実行します。重要な技術的詳細として、Go で記述される
runc ランタイムがあり、これは初期システムコールの処理に C モジュールを使用して Linux カーネルとインターフェースする必要があります。Go は fork などの特定の機能へのネイティブサポートを持っていないため、不足している振る舞いを近似させるために /proc/self/exe などのワークアラウンドが必要です。さらに、標準的な Linux カーネル API は通常ルートの権限を必要とするため、Docker デモンはデフォルトで昇権限(elevated permissions)で動作します。これを解決するためには、ルートレスコンテナランタイムは、通常ルートベースのセットアップが提供する機能を複製するために、ユーザースペースのネットワーキングスタックを再構築する必要があります。結局のところ、これらのアーキテクチャ的な制約を理解することは、安全なルートレス環境を管理するユーザーにとって不可欠であり、不要な権限昇格を避けながらシステム安定性を維持する互換性のあるインフラを設計する企業にとっても重要です。本文
Docker の奇妙な事実を学ぶ体験談
娯楽のために自分専用のコンテナランタイムを作成するプロジェクトを開始し、Docker の背後にある不思議な仕組みに気づき始めました。以下に学んだ重要な事実を整理します。
1. コンテナは「実在」していない
仮想マシン(VM)とは異なり、コンテナは単に特殊な制限がかけられているプロセスに過ぎません。Linux カーネルはこのプロセスを実行し続けており、通常の
/proc ディレクトリ下でそのプロセスを確認できます。
2. 「コンテナ」という概念は単一の機能ではない
Linux カーネルには「コンテナ」という固有の機能は存在せず、5 つの異なる技術の集まりです(これをマントコートのついたものになぞらえ、
trenchcoat と呼ぶこともあります)。それぞれ以下のような役割を果たしています。
- Namespaces: ホストとコンテナが見える範囲を隔離し隠蔽します。
- cgroups: コンテナのリソース使用量を制限します。
- ネットワーク: コンテナのネットワークを孤立させるための一連の仕組みが存在します。
3. イメージは単なるフォルダーに過ぎない
Docker はイメージを配置し、
chroot(または pivot_root)を実行することで、そのフォルダーをコンテナプロセスの新しいルートディレクトリとして指定するだけです。
例:
docker run -it --rm ubuntu /bin/bash を実行すると、以下のような手順で動作します。
- Docker Hub から
のイメージをダウンロードします。ubuntu - ダウンロードしたファイルをディスク上の特定の場所に保存します。
を直接実行します。/some/weird/docker/path/bin/bash
4. Go はコンテナランタイムには相応しくない言語である
Docker のコンテナランタイム
runc は Go で記述されていますが、Go の設計上の決断により用途に不適切な側面があります。
- マルチスレッド構造の問題: Go のランタイムは生来のマルチスレッド構造を持っていますが、
ではシングルスレッド環境下でのみ動作する Linux システムコール(syscalls)を処理する必要があるため課題となります。runc - フォークの欠如: Go には
関数がありません。コンテナランタイムは制限を設定してから実際にプロセスを実行(fork
)する前に、本来的にexec
したい挙動をする必要があります。fork
この問題を回避するため、
runc は以下の方法を採っています:
# /proc/self/exe を実行し、「子プロセス」として振る舞うようにシミュレーション /proc/self/exe <特別なコマンドライン引数>
5. Docker は root ユーザーが必須(場合による)
Mac OS などで Docker を運用する場合、以下の点に注意が必要です。
- 権限の必要性: コンテナランタイムが利用する Linux カーネル API の多くは、root 権限で実行する必要があります。そのため、Docker デーモンは通常 root ユーザーとして動作します。
- ネットワークと Rootless: ネットワーク機能については例外があり、Rootless コンテナランタイムを使用する場合、ユーザー空間で完全な機能を確保するにはネットワークスタック全体を実装し直す必要があるようです。
6. 学習は楽しい!
自分専用のコンテナランタイム開発はまだ初期段階ですが、普段使っているツールを自作することでその仕組みを理解できると実感しました。