2つのプロセスAとBの場合、どちらもライブラリlibc.soを使用し、libc.soはメモリに1回だけロードされます。これは、AとBが同じホストと同じrootfsで実行されている場合の通常の状況です。
コンテナーに関して言えば、AとBが異なるコンテナーで実行されている場合、AとBは同じメモリー領域を共有していますか?
例えば
imageA
--libc.so
--programA
imageB
--libc.so
--programB
chrootを使用して、AとBを異なるrootfsで実行します。 2つのlibc.soは同じです。 libc.soはメモリに2回ロードされますか?
実際、共有ライブラリlibc.so canを使用するプロセスAとBは同じメモリを共有します。多少非直感的には、使用しているDockerストレージドライバーによって異なります。共有ライブラリファイルを同じDockerレイヤーにあるときに同じデバイス/ inodeから発信されたものとして公開できるストレージドライバーを使用する場合、それらは同じ仮想メモリキャッシュページを共有します。 aufs、overlay、overlay2ストレージドライバを使用する場合、共有ライブラリはメモリを共有しますが、他のストレージドライバを使用する場合は共有しません。
なぜこの詳細がDockerのドキュメントでより明確に明らかにされていないのかはわかりません。または多分それはそうですが、私はそれを逃しました。高密度のコンテナを実行しようとする場合、それは重要な差別化要素のようです。
ホストに表示される2つの異なるコンテナーからのプロセスの物理アドレス(/ proc/pid/pagemap)を比較することにより、異なるコンテナーの.soが同じ物理メモリを共有しているかどうかを確認できます。
# ps -ef | grep Java | grep -v grep | awk '{ print $2 }'
3906
4018
# Sudo pmap -X 3906 | grep -e "Address" -e "libpthread"
Address Perm Offset Device Inode Size Rss Pss Referenced Anonymous LazyFree ShmemPmdMapped Shared_Hugetlb Private_Hugetlb Swap SwapPss Locked Mapping
7f97d9249000 r-xp 00000000 fd:00 135202206 104 104 52 104 0 0 0 0 0 0 0 0 libpthread-2.27.so
# Sudo pmap -X 4018 | grep -e "Address" -e "libpthread"
Address Perm Offset Device Inode Size Rss Pss Referenced Anonymous LazyFree ShmemPmdMapped Shared_Hugetlb Private_Hugetlb Swap SwapPss Locked Mapping
7fce739e1000 r-xp 00000000 fd:00 135202206 104 104 52 104 0 0 0 0 0 0 0 0 libpthread-2.27.so
# virt_to_phys_user 3906 0x7f97d9249000
0x59940000
# virt_to_phys_user 4018 0x7fce739e1000
0x59940000
ここに 3906
および4018
は、2つの異なるコンテナで実行されているJavaアプリケーションの2つのインスタンスのホスト上のプロセスIDです。virt_to_phys_userを使用しました。これは、pidとこれからの仮想メモリ link 。物理アドレスは上記の両方のプロセスで同じであることに注意してください。また、両方のインスタンスが同じinode
addrとPss
を持っていることに注意してくださいこれらのページが共有されていることを示します。
ただし、以前の回答で述べたように、この動作は使用するストレージドライバーによって異なります。これはUbuntu 18.04のdocker-ceとRHEL8のpodman(それぞれ、overlay2とoverlay fs)で動作しますが、devicemapperを使用したRHEL 7.5では動作しませんでした。