이것이 U&L 문제인지 아니면그래서질문. 전반적으로 OS와 관련된 내용이므로 U&L에 게시합니다..
배경
내가 아는 한, Linux는 쓰기 중 복사로 메모리 매핑을 통해 공유 라이브러리(.so 파일)를 로드합니다. 이것의 한 가지 장점은 동일한 대규모 라이브러리를 공유하는 여러 프로세스가 해당 라이브러리의 많은 부분에 대해 동일한 물리적 RAM을 공유한다는 것입니다.
프로세스가 "이미지"를 기반으로 하는 자체 "컨테이너"에서 실행되고 각 이미지에는 자체 공유 라이브러리 복사본이 포함되어 있기 때문에 Docker에서는 이런 일이 반드시 발생하는 것은 아닙니다. 이는 의도적인 것입니다. 이를 통해 프로그램은 시스템에 설치된 라이브러리와 크게 다를 수 있는 자체 종속성(라이브러리)을 제공할 수 있습니다.
따라서 Docker 호스트에서 기본적으로 실행되는 프로그램은 Docker 컨테이너 내에서 실행되는 프로그램과 동일한 라이브러리 메모리를 공유하지 않습니다. 왜냐하면 Docker 컨테이너의 프로그램이 라이브러리의 다른 복사본에 매핑되었기 때문입니다.
Docker 레이어 설명
Docker 이미지는 레이어로 생성됩니다. 각 레이어는 다음 레이어에 추가되며 때로는 기존 파일을 덮어쓰기도 합니다. 모든 레이어의 모든 파일이 변경되는 것은 아닙니다.
Docker를 사용하면 기존 이미지에 새 레이어를 추가하여 새 이미지를 만들 수 있습니다. 이런 일이 발생하면 동일한 레이어를 공유하는 여러 이미지가 생성됩니다. 이러한 이미지는 동일한 파일 중 일부의 동일한 복사본을 공유합니다.
Docker는 최소한 레이어를 분리합니다.앞으로달리다. 예를 들어 Docker Hub에서 이미지를 가져올 때 Docker는 각 이미지의 구성 레이어를 가져와서 이미지를 얻습니다. 아직 가지고 있지 않은 레이어만 가져옵니다.
나는 무엇을 모른다
컨테이너를 생성하거나 실행할 때 Docker는 레이어를 일관된 단일 파일 시스템으로 조합해야 합니다. 어떻게 이런 일이 일어나는지 모르겠습니다. 그것은 다음을 수행할 수 있습니다:
- 파일을 한곳에 복사
- 한 곳에서 하드 링크 생성
- 사용파일 시스템 덮어쓰기
역할에 따라 동일한 계층에서 생성된 파일은 파일 시스템의 동일한 복사본이거나 동일한 파일일 수 있습니다.
이는 궁극적으로 파일이 여러 프로세스에 의해 매핑된 메모리일 때 발생하는 상황에 영향을 미칩니다.
내가 정말로 발견하고 싶은 것은 무엇인가?
두 개의 서로 다른 이미지에서 두 개의 컨테이너를 실행하면 단일 레이어에서 발생하는 단일 공유 라이브러리에 대해 동일한 RAM을 공유하는지 궁금합니다.
답변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)
...
다음 두 셸에서 사용되는 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를 가지므로 동일한 파일이며 가능한 경우 해당 매핑이 공유됩니다.