Docker

docker容器是否為從同一層映射但不同圖像的文件記憶體共享RAM?

  • September 30, 2021

我不能 100% 確定這是 U&L 問題還是SO問題。總的來說,我將它發佈在 U&L 上,因為它與作業系統相關

背景

據我所知,Linux 將通過將共享庫(.so 文件)映射為寫時複製來載入共享庫(.so 文件)。這樣做的一個優點是,共享同一個大型庫的多個程序都將共享相同的物理 RAM,用於該庫的大部分內容。

Docker 不一定會發生這種情況,因為程序在基於“映像”的自己的“容器”中執行,並且每個映像都包含它自己的共享庫副本。這是故意的。它允許程序附帶它們自己的依賴項(庫),這些依賴項可能與系統上已安裝的庫有很大不同。

因此,在 docker 主機上本地執行的程序不會與在 docker 容器中執行的程序共享相同的庫記憶體,因為 docker 容器中的程序已映射到庫的不同副本。

Docker 層解釋

Docker 鏡像是分層創建的。每一層都添加到較低的一層,有時會覆蓋現有文件。並非每個文件都在每一層中更改。

Docker 允許您通過向舊圖像添加新層來創建新圖像。發生這種情況時,您最終會得到多個共享相同圖層的圖像。這些圖像共享一些相同文件的相同副本。

Docker 將這些層分開保存,至少執行時之前是這樣。例如:從 Docker Hub 拉取圖像,Docker 通過獲取每個圖像的組成層來獲取圖像。它只獲取它還沒有的層。

我不知道的

在創建或執行容器時,Docker 必須將這些層組裝成一個單一的連貫文件系統。我不知道它是怎麼做到的。它可能:

根據它的作用,源自同一層的文件可能是相同的副本,或者它們可能是文件系統上的完全相同的文件。

這最終會影響文件被多個程序映射到記憶體時發生的情況。

我真正想發現什麼?

我想知道從兩個不同的圖像執行兩個容器是否會為源自單個層的單個共享庫共享相同的 RAM。

至少在某些配置中,是的,容器可以共享不同映像中同一層中的文件的記憶體映射。

這是一個實驗來證明這一點。我正在使用兩個不同的圖像,一個基於另一個:

$ 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
...

我啟動了兩個容器,僅使用入口點 shell:

$ pstree -p
...
          ├─containerd-shim(530457)─┬─bash(530477)
          │                         ├─{containerd-shim}(530458)
...
          ├─containerd-shim(530622)─┬─entry(530643)───sh(530685)
          │                         ├─{containerd-shim}(530624)
...

讓我們檢查一下這兩個 shell 使用的 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,因此它們是同一個文件,並且它們的映射將在可能的情況下共享。

引用自:https://unix.stackexchange.com/questions/671259