これがU&Lの問題かどうかだから質問。全体的にOSに関連する内容なのでU&Lに投稿します。。
背景
私が知る限り、Linuxは書き込み中のコピーへのメモリマッピングを介して共有ライブラリ(.soファイル)をロードします。これの1つの利点は、同じ大規模ライブラリを共有する複数のプロセスが、そのライブラリの大部分に対して同じ物理RAMを共有することです。
プロセスは「イメージ」に基づく独自の「コンテナ」で実行され、各イメージには独自の共有ライブラリのコピーが含まれているため、Dockerではこれは必ずしも起こりません。これは意図的なものです。これにより、プログラムはシステムにインストールされているライブラリとは大きく異なる独自の依存関係(ライブラリ)を提供できます。
したがって、Dockerホストでデフォルトで実行されるプログラムは、Dockerコンテナ内で実行されているプログラムと同じライブラリメモリを共有しません。なぜなら、Dockerコンテナのプログラムがライブラリの他のコピーにマップされているからです。
Dockerレイヤーの説明
Docker イメージはレイヤーで作成されます。各レイヤーは次のレイヤーに追加され、時には既存のファイルを上書きすることもあります。すべてのレイヤーのすべてのファイルが変更されるわけではありません。
Dockerを使用すると、既存の画像に新しいレイヤーを追加して新しい画像を作成できます。これが発生すると、同じレイヤを共有する複数の画像が作成されます。これらのイメージは、同じファイルの一部の同じコピーを共有します。
Dockerは少なくともレイヤーを分離します。今後走る。たとえば、Docker Hub からイメージをインポートすると、Docker は各イメージの構成レイヤーをインポートしてイメージを取得します。まだ持っていないレイヤーのみを取得します。
私は何を知らない
コンテナを作成または実行するときは、Dockerはレイヤを一貫した単一のファイルシステムにまとめる必要があります。どうやってこれが起こるのかわかりません。それは次のことができます:
- ファイルを1か所にコピー
- 一箇所でハードリンクを作成
- 使用ファイルシステムの上書き
役割に応じて、同じ階層で作成されたファイルは、ファイルシステムの同じコピーでも同じファイルでもかまいません。
これは最終的にファイルが複数のプロセスによってマッピングされたメモリである場合に発生する状況に影響します。
私が本当に見つけたいものは何ですか?
2 つの異なるイメージで 2 つのコンテナを実行すると、1 つのレイヤで発生する 1 つの共有ライブラリに対して同じ RAM を共有するかどうか疑問に思います。
答え1
少なくとも一部の構成では、コンテナは異なるイメージ内の同じファイル層のメモリマッピングを共有できます。
これを証明するための実験があります。私は2つの異なる画像を使用しています。 1つはもう1つに基づいています。
$ docker history 5f35156022ae
IMAGE CREATED CREATED BY SIZE COMMENT
5f35156022ae 7 weeks ago COPY scripts/shared/ . # buildkit 1.05MB buildkit.dockerfile.v0
<missing> 7 weeks ago WORKDIR /opt/shipyard/scripts 0B buildkit.dockerfile.v0
...
$ docker history 569bf4207a08
IMAGE CREATED CREATED BY SIZE COMMENT
569bf4207a08 7 weeks ago /bin/sh -c #(nop) CMD ["sh"] 0B
ed9510deb54e 7 weeks ago /bin/sh -c #(nop) ENTRYPOINT ["/opt/shipyar… 0B
c3e0351f0dd2 7 weeks ago /bin/sh -c #(nop) WORKDIR /go/src/github.com… 0B
a476f9f2b118 7 weeks ago /bin/sh -c #(nop) ENV DAPPER_OUTPUT=/go/src… 0B
29a76c4ff3e7 7 weeks ago /bin/sh -c #(nop) ENV DAPPER_ENV=QUAY_USERN… 0B
2f4a590d61ef 7 weeks ago /bin/sh -c #(nop) ARG PROJECT 0B
5f35156022ae 7 weeks ago COPY scripts/shared/ . # buildkit 1.05MB buildkit.dockerfile.v0
<missing> 7 weeks ago WORKDIR /opt/shipyard/scripts 0B buildkit.dockerfile.v0
...
エントリポイントシェルのみを使用して両方のコンテナを起動しました。
$ pstree -p
...
├─containerd-shim(530457)─┬─bash(530477)
│ ├─{containerd-shim}(530458)
...
├─containerd-shim(530622)─┬─entry(530643)───sh(530685)
│ ├─{containerd-shim}(530624)
...
次の2つのシェルで使用されているCライブラリを見てみましょう。
$ sudo grep libc-2.33 /proc/{530477,530685}/maps
/proc/530477/maps:7fc127f81000-7fc127fa7000 r--p 00000000 00:1f 3117 /usr/lib64/libc-2.33.so
/proc/530477/maps:7fc127fa7000-7fc1280f4000 r-xp 00026000 00:1f 3117 /usr/lib64/libc-2.33.so
/proc/530477/maps:7fc1280f4000-7fc128140000 r--p 00173000 00:1f 3117 /usr/lib64/libc-2.33.so
/proc/530477/maps:7fc128140000-7fc128141000 ---p 001bf000 00:1f 3117 /usr/lib64/libc-2.33.so
/proc/530477/maps:7fc128141000-7fc128144000 r--p 001bf000 00:1f 3117 /usr/lib64/libc-2.33.so
/proc/530477/maps:7fc128144000-7fc128147000 rw-p 001c2000 00:1f 3117 /usr/lib64/libc-2.33.so
/proc/530685/maps:7f6a5df94000-7f6a5dfba000 r--p 00000000 00:1f 3117 /usr/lib64/libc-2.33.so
/proc/530685/maps:7f6a5dfba000-7f6a5e107000 r-xp 00026000 00:1f 3117 /usr/lib64/libc-2.33.so
/proc/530685/maps:7f6a5e107000-7f6a5e153000 r--p 00173000 00:1f 3117 /usr/lib64/libc-2.33.so
/proc/530685/maps:7f6a5e153000-7f6a5e154000 ---p 001bf000 00:1f 3117 /usr/lib64/libc-2.33.so
/proc/530685/maps:7f6a5e154000-7f6a5e157000 r--p 001bf000 00:1f 3117 /usr/lib64/libc-2.33.so
/proc/530685/maps:7f6a5e157000-7f6a5e15a000 rw-p 001c2000 00:1f 3117 /usr/lib64/libc-2.33.so
両方のマッピングライブラリは同じデバイスと inode を持つため、同じファイルであり、可能であれば、対応するマッピングが共有されます。