Docker 이미지 "레이어"란 무엇입니까?


165

Docker를 처음 접했고 Docker 이미지 가 무엇인지 정확하게 이해하려고합니다 . Docker 이미지의 모든 단일 정의는 "layer"라는 용어를 사용하지만 layer의 의미를 정의하지는 않습니다 .

공식 Docker 문서에서 :

Docker 이미지는 Docker 컨테이너가 시작되는 읽기 전용 템플릿이라는 것을 이미 알고 있습니다. 각 이미지는 일련의 레이어로 구성됩니다. Docker는 통합 파일 시스템을 사용하여 이러한 레이어를 단일 이미지로 결합합니다. 통합 파일 시스템은 브랜치 (branch)라고하는 별도의 파일 시스템의 파일과 디렉토리를 투명하게 겹쳐 단일 코 히어 런트 파일 시스템을 형성합니다.

그래서 나는 층이 무엇인지 묻습니다. 누군가가 그들에게 몇 가지 구체적인 예를 줄 수 있습니까? 그리고이 레이어들은 어떻게 이미지를 형성하기 위해 "함께 스냅"합니까?

답변:


133

나는 늦을지도 모르지만 여기에 10 센트가 있습니다 (ashishjain의 답변을 보완 함).

기본적으로 레이어 또는 이미지 레이어 는 이미지 또는 중간 이미지의 변경 입니다. 사용자가 지정하는 모든 명령 ( FROM, RUN, COPY당신 Dockerfile에서, 등) 따라서 새 레이어를 생성, 변화에 이전 이미지가 발생합니다. git을 사용할 때 스테이징 변경으로 생각할 수 있습니다. 파일 변경 사항을 추가 한 다음 다른 변경 사항을 추가하십시오.

다음 Dockerfile을 고려하십시오.

FROM rails:onbuild
ENV RAILS_ENV production
ENTRYPOINT ["bundle", "exec", "puma"]

먼저 시작 이미지를 선택합니다 . rails:onbuild레이어 에는 여러 레이어가 있습니다. 시작 이미지 위에 다른 레이어를 추가 RAILS_ENV하고 ENV명령으로 환경 변수 를 설정합니다 . 그런 다음 docker에게 bundle exec puma(레일 서버를 부팅) 실행하도록 지시합니다 . 그것은 또 다른 층입니다.

레이어 개념은 이미지를 만들 때 유용합니다. 레이어는 중간 이미지이므로 Dockerfile을 변경하면 docker 는 변경된 레이어와 그 이후의 레이어 빌드 합니다. 이것을 레이어 캐싱이라고합니다.

자세한 내용은 여기를 참조 하십시오 .


13
레이어를 변경하거나 추가하면 Docker는 변경으로 인해 영향을받을 수 있으므로 이후에 오는 레이어도 빌드합니다.
Adam

다른 답변에서 누락 된 레이어 개념의 이유를 설명해 주셔서 감사합니다.
Seeta Somagani

@David, 위의 예에서 몇 개의 레이어가 추가됩니까? 2? 또는 1?
Gourav Singla

1
@GouravSingla 2 여야합니다. 변경 ENV도 변경됩니다. 레이어가 git의 커밋 인 것 같습니다.
PokerFace

마지막 웹 링크 ( https://labs.ctl.io/caching-docker-images/)가 손상되었습니다. 교체에 대한 제안이 있습니까?
Johnny Utahh

72

docker 컨테이너 이미지는 dockerfile을 사용하여 생성됩니다 . dockerfile의 모든 줄은 레이어를 만듭니다. 다음 더미 예제를 고려하십시오.

FROM ubuntu             #This has its own number of layers say "X"
MAINTAINER FOO          #This is one layer 
RUN mkdir /tmp/foo      #This is one layer 
RUN apt-get install vim #This is one layer 

그러면 총 레이어 수가 X + 3 인 최종 이미지가 생성됩니다.


32
내가 공감하지는 않았지만 이것이 레이어 를 만드는 방법을 설명 하지만 레이어가 무엇인지에 대한 질문에 대답하지는 않을 것 입니다.
Lasse V. Karlsen

2
@ LasseV.Karlsen, ashishjain에 동의합니다. 나는 당신을 downvote하지 않았고 실제로 나를 도와 주려고 노력하여 당신을 찬성하고 있습니다. 다시 한 번 감사드립니다.
smeeb

3
최고의 답변 imo. "도커 활용"으로 이동하는 많은 사람들에게 레이어 작동 방식의 요점을 알려줍니다.
dtc

6
"dockerfile의 모든 라인은 레이어를 생성합니다."-이것은 내가 아는 데 매우 도움이되었습니다
akirekadu

2
@akirekadu 그것은 전체 이야기가 아닙니다. 대부분의 선은 레이어를 만들지 만 ADD, COPY 또는 RUN 명령 만 결과 컨테이너 이미지의 크기를 증가시키는 레이어를 만듭니다. 명령을 연결하거나 백 슬래시로 줄 바꿈을 이스케이프하면 일련의 연결 명령 / 이스케이프 된 줄 바꿈이 단일 명령을 형성하기 때문에 대부분의 줄을 말했습니다.
Scott Simontis

41

그들은 예를 들어 나에게 가장 의미가 있습니다 ...

docker diff로 자신의 빌드 레이어 검사

독창적 인 Dockerfile 예제를 보자.

FROM busybox

RUN mkdir /data
# imagine this is downloading source code
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/one 
RUN chmod -R 0777 /data
# imagine this is compiling the app
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/two 
RUN chmod -R 0777 /data
# and now this cleans up that downloaded source code
RUN rm /data/one 

CMD ls -alh /data

이러한 각 dd명령은 1M 파일을 디스크에 출력합니다. 임시 컨테이너를 저장하기 위해 추가 플래그를 사용하여 이미지를 빌드 할 수 있습니다.

docker image build --rm=false .

출력에서 실행중인 각 명령이 자동 컨테이너 대신 삭제되는 임시 컨테이너에서 발생하는 것을 볼 수 있습니다.

...
Step 2/7 : RUN mkdir /data
 ---> Running in 04c5fa1360b0
 ---> 9b4368667b8c
Step 3/7 : RUN dd if=/dev/zero bs=1024 count=1024 of=/data/one
 ---> Running in f1b72db3bfaa
1024+0 records in
1024+0 records out
1048576 bytes (1.0MB) copied, 0.006002 seconds, 166.6MB/s
 ---> ea2506fc6e11

docker diff각 컨테이너 ID에서 를 실행하면 해당 컨테이너에서 어떤 파일이 생성되었는지 확인할 수 있습니다.

$ docker diff 04c5fa1360b0  # mkdir /data
A /data
$ docker diff f1b72db3bfaa  # dd if=/dev/zero bs=1024 count=1024 of=/data/one
C /data
A /data/one
$ docker diff 81c607555a7d  # chmod -R 0777 /data
C /data
C /data/one
$ docker diff 1bd249e1a47b  # dd if=/dev/zero bs=1024 count=1024 of=/data/two
C /data
A /data/two
$ docker diff 038bd2bc5aea  # chmod -R 0777 /data
C /data/one
C /data/two
$ docker diff 504c6e9b6637  # rm /data/one
C /data
D /data/one

접두사가 붙은 각 줄 A은 파일을 추가하고, C기존 파일의 변경을 D나타내며, 삭제를 나타냅니다.

TL; DR 부분은 다음과 같습니다.

위의 각 컨테이너 파일 시스템 차이는 이미지를 컨테이너로 실행할 때 조립되는 하나의 "계층"으로 들어갑니다. 추가 또는 변경이있을 때 전체 파일은 각 레이어에 있습니다.chmod 권한 비트 만 변경하더라도 명령이 전체 파일이 다음 계층으로 복사됩니다. 삭제 된 / data / one 파일은 여전히 ​​이전 레이어에 있으며 실제로 3 번이며 이미지를 가져올 때 네트워크를 통해 복사되어 디스크에 저장됩니다.

기존 이미지 검사

명령으로 기존 이미지의 레이어를 만드는 명령을 볼 수 있습니다 docker history. docker image inspect이미지에서 이미지를 실행할 수도 있고 RootFS 섹션에서 계층 목록을 볼 수도 있습니다.

위 이미지의 기록은 다음과 같습니다.

IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
a81cfb93008c        4 seconds ago       /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "ls -…   0B
f36265598aef        5 seconds ago       /bin/sh -c rm /data/one                         0B
c79aff033b1c        7 seconds ago       /bin/sh -c chmod -R 0777 /data                  2.1MB
b821dfe9ea38        10 seconds ago      /bin/sh -c dd if=/dev/zero bs=1024 count=102…   1.05MB
a5602b8e8c69        13 seconds ago      /bin/sh -c chmod -R 0777 /data                  1.05MB
08ec3c707b11        15 seconds ago      /bin/sh -c dd if=/dev/zero bs=1024 count=102…   1.05MB
ed27832cb6c7        18 seconds ago      /bin/sh -c mkdir /data                          0B
22c2dd5ee85d        2 weeks ago         /bin/sh -c #(nop)  CMD ["sh"]                   0B
<missing>           2 weeks ago         /bin/sh -c #(nop) ADD file:2a4c44bdcb743a52f…   1.16MB

최신 레이어가 맨 위에 나열됩니다. 참고로, 바닥에는 상당히 오래된 두 개의 레이어가 있습니다. 비지 박스 이미지 자체에서 가져옵니다. 하나의 이미지를 만들면 FROM라인에 지정한 이미지의 모든 레이어가 상속 됩니다. 이미지 메타 데이터 변경을 위해 추가되는 레이어도 있습니다.CMD라인 . 공간을 거의 차지하지 않으며 실행중인 이미지에 적용되는 설정을 기록하는 데 더 좋습니다.

왜 레이어인가?

레이어에는 몇 가지 장점이 있습니다. 첫째, 그들은 불변입니다. 일단 생성되면 sha256 해시로 식별되는 해당 계층은 절대 변경되지 않습니다. 이러한 불변성은 이미지가 서로 안전하게 빌드되고 포크 될 수있게합니다. 두 개의 도커 파일이 동일한 초기 라인 세트를 갖고 동일한 서버에 빌드 된 경우 동일한 초기 레이어 세트를 공유하여 디스크 공간을 절약합니다. 즉, Dockerfile의 마지막 몇 줄만 변경되어 이미지를 다시 빌드하는 경우 해당 레이어 만 다시 빌드하면되고 나머지는 레이어 캐시에서 재사용 할 수 있습니다. 이렇게하면 도커 이미지를 매우 빠르게 재구성 할 수 있습니다.

컨테이너 내부에는 이미지 파일 시스템이 표시되지만 해당 파일 시스템은 복사되지 않습니다. 이러한 이미지 레이어 위에 컨테이너는 자체 읽기 / 쓰기 파일 시스템 레이어를 마운트합니다. 파일의 모든 읽기는 파일을 삭제하도록 표시 한 레이어에 도달하거나 해당 레이어에 파일의 사본이 있거나 읽기에 레이어가 부족하여 검색 할 때까지 레이어를 통과합니다. 모든 쓰기는 컨테이너 특정 읽기 / 쓰기 레이어를 수정합니다.

레이어 팽창 감소

레이어의 한 가지 단점은 파일을 복제하거나 이후 레이어에서 삭제 된 파일을 배송하는 이미지를 만드는 것입니다. 해결책은 종종 여러 명령을 단일 RUN명령 으로 병합하는 것 입니다. 특히 기존 파일을 수정하거나 파일을 삭제하는 경우 해당 단계가 처음 작성된 동일한 명령으로 실행되기를 원합니다. 위의 Dockerfile을 다시 작성하면 다음과 같습니다.

FROM busybox

RUN mkdir /data \
 && dd if=/dev/zero bs=1024 count=1024 of=/data/one \
 && chmod -R 0777 /data \
 && dd if=/dev/zero bs=1024 count=1024 of=/data/two \
 && chmod -R 0777 /data \
 && rm /data/one

CMD ls -alh /data

그리고 결과 이미지를 비교하면 :

  • 비지 박스 : ~ 1MB
  • 첫 번째 이미지 : ~ 6MB
  • 두 번째 이미지 : ~ 2MB

고려 된 예제에서 몇 줄을 병합하여 이미지에 동일한 결과 콘텐츠를 얻었으며 이미지를 5MB에서 최종 이미지에 표시되는 1MB 파일로 축소했습니다.


파일을 읽는 동안 레이어를 순회하면 약간의 오버 헤드가 필요합니다. 이 오버 헤드를 줄이기 위해 여러 명령 (어쨌든 함께 실행해야 함)을 하나의 RUN으로 결합하는 것이 합리적입니까?
SergiyKolesnikov

@SergiyKolesnikov는 조기 최적화에 얼마나 많은 시간을 소비하고 싶은가에 달려 있습니다. 위험은 밀리 초의 런타임을 절약하기 위해 몇 시간의 개발자 시간, 추가 된 대역폭 및 저장 공간을 소비하는 것입니다. 성능과 관련된 많은 것들과 마찬가지로 극단적 인 문제가 있으며 문제를 해결하기 전에 문제를 측정해야합니다.
BMitch

19

Docker v1.10부터 컨텐츠 주소 지정 가능 스토리지가 도입되면서 '레이어'라는 개념이 크게 달라졌습니다. 레이어는 이미지에 대한 개념이 없거나 이미지에 속하지 않으며 이미지 전체에서 공유 할 수있는 파일 및 디렉토리의 모음이됩니다. 레이어와 이미지가 분리되었습니다.

예를 들어, 기본 이미지에서 로컬 내장 이미지에의 말을하자 ubuntu:14.04docker history명령은 이미지 체인을 산출하지만 이미지 ID의 일부는 빌드 역사는 더 이상로드되어 있기 때문에 '실종 없다'로 표시됩니다. 이러한 이미지를 구성하는 레이어는

docker inspect <image_id> | jq -r '.[].RootFS'

/var/lib/docker/aufs/diff스토리지 드라이버 선택이 인 경우 계층 컨텐츠가에 저장됩니다 aufs. 그러나 레이어는 임의로 생성 된 캐시 ID로 이름이 지정되며 보안상의 이유로 레이어와 캐시 ID 간의 링크는 Docker Engine에만 알려져 있습니다. 나는 아직도 알아낼 방법을 찾고있다

  1. 이미지와 구성 레이어 간의 대응 관계
  2. 디스크에서 레이어의 실제 위치 및 크기

블로그 는 많은 통찰력을 제공했습니다.


SO 항목에서 나는 내가 게시 한 두 가지 질문에 대답하는 다소 순진한 방법을 게시했습니다.
Ruifeng Ma

13

Moby Project 를 통한 Docker의 이미지 사양 :

이미지는 레이어로 구성됩니다. 각 계층은 일련의 파일 시스템 변경입니다. 레이어에는 환경 변수 또는 기본 인수와 같은 구성 메타 데이터가 없습니다. 이는 특정 레이어가 아닌 이미지 전체의 속성입니다.

따라서 기본적으로 계층은 파일 시스템에 대한 일련의 변경 사항입니다.


그것을 찾는 데 몇 시간 밖에 걸리지 않았지만 우아하고 간단한 대답으로 마침내 레이어가 무엇인지 이해했습니다 "Each [Docker] layer is a set of filesystem changes.". blogs / Q + A 's / etc, 그리고 나는 그 한계가 내 ​​것이 아니라고 생각합니다. 어쨌든, 문제의 핵심에 도달하기위한 브라보 Aditya.
Johnny Utahh


2

유용한 정보 는 @David Castillo에게 감사드립니다 . 레이어는 이진 변경 또는 쉽게 수행하거나 취소 할 수있는 이미지의 명령이라고 생각합니다. 레이어의 레이어와 동일한 단계적으로 수행되므로 "레이어"라고합니다.

자세한 내용은 다음과 같이 "docker history"를 볼 수 있습니다.

도커 이미지 --tree
경고 : '--tree'는 더 이상 사용되지 않으며 곧 제거됩니다. 사용법을 참조하십시오.
└─511136ea3c5a 가상 크기 : 0 B 태그 : 스크래치 : 최신
  └─59e359cb35ef 가상 크기 : 85.18 MB
    └─e8d37d9e3476 가상 크기 : 85.18 MB 태그 : debian : wheezy
      └─c58b36b8f285 가상 크기 : 85.18MB
        └─90ea6e05b074 가상 크기 : 118.6 MB
          └─5dc74cffc471 가상 크기 : 118.6 MB 태그 : vim : latest


5
계층 에 대한 새로운 정보를 찾았습니다 : Docker가 rootfs를 마운트 할 때 전통적인 Linux 부팅에서와 같이 읽기 전용으로 시작되지만 파일 시스템을 읽기 / 쓰기 모드로 변경하는 대신 통합 마운트를 사용하여 추가합니다. 읽기 전용 파일 시스템을 통한 읽기 / 쓰기 파일 시스템 실제로 여러 개의 읽기 전용 파일 시스템이 서로 쌓여있을 수 있습니다. 우리는이 파일 시스템들 각각을 하나의 계층으로 생각 합니다.
hiproz

1

내 개인적인 이해는 docker layer와 github commit을 비교할 수 있다는 것입니다. 기본 이미지 (신선한 마스터 저장소)의 경우 여러 커밋을 수행하고 모든 커밋이 마스터 상태를 변경하고 도커에서도 동일하며 모든 레이어가 이전 중간 레이어를 기반으로 일부 작업을 수행합니다. 그리고이 레이어는 다음 레이어의 새로운 중간 레이어가됩니다.


0

나는 그들이 같은 생각 이전 레이어의 차이점 . 여기에 대한 답변 중 일부를 읽은 후 확신이 없었습니다. 그것들은 파일 시스템에 대한 일련의 변경으로 설명된다 . 나는 Dockerfile을 작성하여 diff와 더 비슷하다는 것을 보여주었습니다. 즉, 이전 레이어에 실제로 의존합니다.

이 두 Dockerfile이 주어지면

FROM bash
RUN mkdir /data
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/one
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/two
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/three

FROM bash
RUN mkdir /data
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/three
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/two
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/one

파일 시스템의 변경에 관한 것이라면 동일한 레이어 세트를 기대할 수 있지만, 그렇지 않습니다.

$ docker history img_1
IMAGE               CREATED             CREATED BY                                      SIZE
30daa166a9c5        6 minutes ago       /bin/sh -c dd if=/dev/zero bs=1024 count=102…   1.05MB
4467d16e79f5        6 minutes ago       /bin/sh -c dd if=/dev/zero bs=1024 count=102…   1.05MB
c299561fd031        6 minutes ago       /bin/sh -c dd if=/dev/zero bs=1024 count=102…   1.05MB
646feb178431        6 minutes ago       /bin/sh -c mkdir /data                          0B
78664daf24f4        2 weeks ago         /bin/sh -c #(nop)  CMD ["bash"]                 0B
<missing>           2 weeks ago         /bin/sh -c #(nop)  ENTRYPOINT ["docker-entry…   0B
<more missing...>

$ docker history img_2
IMAGE               CREATED             CREATED BY                                      SIZE
f55c91305f8c        6 minutes ago       /bin/sh -c dd if=/dev/zero bs=1024 count=102…   1.05MB
29b3b627c76f        6 minutes ago       /bin/sh -c dd if=/dev/zero bs=1024 count=102…   1.05MB
18360be603aa        6 minutes ago       /bin/sh -c dd if=/dev/zero bs=1024 count=102…   1.05MB
646feb178431        6 minutes ago       /bin/sh -c mkdir /data                          0B
78664daf24f4        2 weeks ago         /bin/sh -c #(nop)  CMD ["bash"]                 0B
<missing>           2 weeks ago         /bin/sh -c #(nop)  ENTRYPOINT ["docker-entry…   0B
<more missing...>

파일 시스템에 대한 변경 사항이 두 경우 모두 동일 하더라도 순서가 어떻게 중요한지 알 수 있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.