こんにちは!今日は、Dockerコンテナが実際にデータをどのように保存・管理しているのか、その「魔法」のような構造を直接目で確認する時間を持とうと思います。
多くの方がコンテナを使用していますが、実際のファイルがどこに、どのように存在しているのか疑問に思っています。DockerはOverlayFS(Overlay Filesystem)という技術を使って、複数のレイヤーをあたかも一つのファイルシステムであるかのように結合して表示します。
今日は複雑な理論の代わりに、直接コマンドを打ちながらホストOSの観点からコンテナの内部構造を徹底的に見ていきましょう。準備はいいですか?🚀

1. 実験対象の準備:コンテナの実行 🏃♂️
まず、分析するコンテナを一つ実行してみましょう。軽量で高速なnginx:alpineイメージを使用します。
# Nginxコンテナを実行(バックグラウンドモード)
docker run -d -p 80:80 --name nx nginx:alpine
これでNginxは隔離された環境で動作しています。しかし、Linuxカーネルの観点から見ると、これは単なる一つのプロセスに過ぎません。
2. Overlayの秘密の地図:Mountinfoの確認 🗺️
さて、最も重要なステップです!このプロセスが見ているファイルシステムが実際にどのように組み立てられているのか、/procファイルシステムを通じて確認してみましょう。
# 該当マウント情報からoverlayfs設定値を照会
mount | grep rootfs
出力例:
overlay on /var/lib/docker/rootfs/overlayfs/fea3c44e1dee873838bee303f32d739164f9a34e6a38b3c99ccc3c6e88f7e702 type overlay (rw,relatime,lowerdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/9/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/8/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/7/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/6/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/5/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/4/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/3/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/2/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/1/fs,upperdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/10/fs,workdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/10/work,nouserxattr)
このコマンドを実行するとかなり長い文字列が表示されますが、ここで重要なキーワード4つだけを見つければ大丈夫です。
- 🔒 LowerDir(イメージレイヤー):読み取り専用(Read-Only)です。私たちがダウンロードしたnginx:alpineイメージを構成する複数のレイヤーがここに該当します。決して修正されません。
- ✏️ UpperDir(コンテナレイヤー):書き込み可能(Read-Write)領域です。コンテナ内でファイルを作成したり修正したりすると、実際にはここだけに保存されます。
- ⚙️ WorkDir:OverlayFSがファイル結合作業のために内部的に使用する一時的な空間です。
- 👀 Merged(統合ビュー):‘overlay on’の直後に見える/var/lib/docker/rootfs/overlayfs/で始まるパスです。上記のLowerDirとUpperDirが結合されて、私たちの目に見える最終結果物です。コンテナが見る/(ルート)ディレクトリがまさにこれです。
3. ホストからコンテナ内部へ「瞬間移動」する 🚪
コンテナ内部に接続(docker exec)せずに、ホストからコンテナのファイルを見ることができるでしょうか?はい、可能です!Linuxカーネルは/procディレクトリに裏口を作っておきました。
# 方法1:コンテナIDを通じてMergedディレクトリを確認
ls -al /var/lib/docker/rootfs/overlayfs/$(docker inspect -f '{{.Id}}' nx)
# 方法2:PIDを利用してコンテナのRootFSへ直接移動(推奨!)
ls -al /proc/$(docker inspect -f '{{.State.Pid}}' nx)/root/
/proc/[PID]/root/パスは、該当プロセスが見ているルートディレクトリに接続されるシンボリックリンクのようなものです。ここに入ると、docker execで入った時と同じファイルが見えます。不思議でしょう?✨
4. データ書き込み実験と検証 🧪
本当にホストから見るビューとコンテナが見るビューは繋がっているのでしょうか?テストのためにホストからファイルを一つ作成してみましょう。
# ホストからコンテナのRootパスにファイルを作成
echo test1234 > /proc/$(docker inspect -f '{{.State.Pid}}' nx)/root/test.txt
これでコンテナ内部で確認してみると、test.txtファイルがポンと現れているはずです。この実験が示唆することは大きいです。コンテナファイルシステムは、別途の閉じた空間ではなく、ホストファイルシステムの特定のパスを組み合わせて表示しているものだという点です。
5. 私のファイルは実際にどこにあるのか?💾
先ほど作成したtest.txtファイルは、ホストのハードディスクのどこかに物理的に存在しているはずです。一体どこに保存されたのでしょうか?
# test.txtファイルの実際の物理的位置を探す
find /var/lib/docker/rootfs/ -name test.txt
検索結果を見ると、/var/lib/docker/overlay2/[ハッシュ値]/diff/test.txtのようなパスが表示されるでしょう。
このパスは、まさに先ほどの3番のステップで確認したUpperDirのパスと一致します!つまり、「イメージ(LowerDir)は触らず、変更された事項はすべてUpperDirに別途保存する」というOverlayFSの動作原理を直接確認したことになります。
🎯 結論と要約
今日の演習を通じて、私たちは以下の事実を知ることができました。
- コンテナは魔法の箱ではなく、Linuxプロセスである。
- コンテナのファイルシステムは、読み取り専用イメージ(Lower)の上に書き込み可能レイヤー(Upper)を重ねて結合した(Merged)ものである。
- コンテナを削除するとUpperDirが削除されるため、そこに書き込んだデータも一緒に消える。(だからボリュームが必要なのだ!)
この原理を理解すると、Dockerのイメージビルド速度、コンテナ起動速度がなぜ速いのか、そしてストレージをどのように管理すべきか、より深く理解できるようになります。
今日も楽しいコンテナ航海を!⛵️
コメントを残す