Notice
Recent Posts
Recent Comments
Link
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
Archives
Today
Total
관리 메뉴

csct3434

[도커 공식문서 학습] 8. 이미지 빌드 - 이미지 레이어 이해하기 본문

Docker

[도커 공식문서 학습] 8. 이미지 빌드 - 이미지 레이어 이해하기

csct3434 2025. 3. 31. 10:00

개요

앞서 배운 것처럼, 컨테이너 이미지는 여러 개의 레이어(layer)로 구성됩니다. 그리고 한 번 생성된 각 레이어는 변경할 수 없습니다(불변, immutable). 하지만 이게 실제로 무엇을 의미할까요? 그리고 이러한 레이어가 컨테이너의 파일 시스템을 구성하는 방식은 어떻게 될까요?


이미지 레이어란?

각 이미지 레이어는 파일 시스템의 변경 사항(추가, 삭제, 수정)을 포함하고 있습니다. 예를 들어, 하나의 가상의 이미지를 생각해 봅시다.

  1. 첫 번째 레이어에서는 기본적인 명령어들과 패키지 매니저(예: apt)를 추가합니다.
  2. 두 번째 레이어에서는 Python 실행 환경과 패키지 관리자(pip)를 설치합니다.
  3. 세 번째 레이어에서는 애플리케이션의 requirements.txt 파일을 복사해 넣습니다.
  4. 네 번째 레이어에서는 requirements.txt에 명시된 의존성을 설치합니다.
  5. 다섯 번째 레이어에서는 애플리케이션의 실제 소스 코드를 복사해 넣습니다.

이와 같은 구조 덕분에, 이미지들간에 레이어를 재사용할 수 있습니다. 예를 들어, 또 다른 Python 애플리케이션을 만들고 싶다면, 기존의 Python 실행 환경을 그대로 사용할 수 있습니다. 이렇게 하면 빌드 속도가 빨라지고, 이미지를 배포하기 위한 저장 공간 및 네트워크 대역폭을 절약할 수 있습니다. 이미지 레이어는 다른 사람이 작성한 이미지의 베이스 레이어를 재사용하여, 자신의 애플리케이션에서 필요한 데이터만을 추가하여 이미지를 확장할 수 있도록 해줍니다.


레이어 쌓기(Stacking Layers)

이러한 레이어링이 가능해지는 이유는 콘텐츠 주소 지정 저장소(content-addressable storage)유니온 파일 시스템(union filesystem) 덕분입니다. 기술적인 내용을 살펴보면 다음과 같이 동작합니다.

  1. 컨테이너 이미지를 다운로드하면, 각 레이어는 호스트 파일 시스템의 개별 디렉터리에 압축 해제됩니다.
  2. 컨테이너를 실행할 때, 유니온 파일 시스템이 생성되어 여러 개의 레이어가 하나의 통합된 뷰로 합쳐집니다.
  3. 컨테이너가 시작되면, chroot를 사용하여 컨테이너의 루트 디렉터리가 이 통합된 파일 시스템의 위치로 설정됩니다.
  4. 유니온 파일 시스템이 생성될 때, 실행 중인 컨테이너 전용 디렉터리도 함께 생성됩니다.
    • 이를 통해 컨테이너는 자체적으로 파일 시스템을 수정할 수 있지만, 기존의 이미지 레이어는 변경되지 않습니다.
    • 덕분에 동일한 이미지를 기반으로 여러 개의 컨테이너를 실행할 수 있습니다.

실습: 이미지 레이어 직접 만들기

이번 실습에서는 docker container commit 명령어를 사용하여 직접 새로운 이미지 레이어를 생성해 보겠습니다.
(참고: 실제 환경에서는 보통 Dockerfile을 사용하지만, 개념을 쉽게 이해하기 위해 이 방법을 사용합니다.)


1단계: 기본(Base) 이미지 만들기

1. Docker Desktop을 설치합니다.

 

2. 터미널에서 다음 명령어를 실행하여 새 컨테이너를 시작합니다.

docker run --name=base-container -ti ubuntu

 

 

3. 컨테이너가 실행되면, 다음과 같은 프롬프트가 나타납니다.

root@d8c5ca119fcd:/#

 

4. 컨테이너 내부에서 다음 명령어를 실행하여 Node.js를 설치합니다. 유니온 파일시스템 관점에서, 이러한 파일시스템 변경 사항은 컨테이너의 고유한 디렉터리 안에서 발생합니다.

apt update && apt install -y nodejs

 

5. Node.js가 제대로 설치되었는지 확인하려면 다음 명령어를 실행하세요. (출력 결과: Hello world!)

node -e 'console.log("Hello world!")'

 

6. 이제 이 변경 사항을 새로운 이미지 레이어로 저장합니다.

docker container commit -m "Add node" base-container node-base

 

7. 아래 명령어를 통해 이미지의 레이어들을 확인합니다.

docker image history node-base

------
출력 예시
------
IMAGE          CREATED          CREATED BY                                      SIZE      COMMENT
d5c1fca2cdc4   10 seconds ago   /bin/bash                                       126MB     Add node
2b7cc08dcdbb   5 weeks ago      /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>      5 weeks ago      /bin/sh -c #(nop) ADD file:07cdbabf782942af0…   69.2MB
<missing>      5 weeks ago      /bin/sh -c #(nop)  LABEL org.opencontainers.…   0B
<missing>      5 weeks ago      /bin/sh -c #(nop)  LABEL org.opencontainers.…   0B
<missing>      5 weeks ago      /bin/sh -c #(nop)  ARG LAUNCHPAD_BUILD_ARCH     0B
<missing>      5 weeks ago      /bin/sh -c #(nop)  ARG RELEASE                  0B

 

 

8. 새로운 이미지(node-base)에서 컨테이너를 실행하여 Node.js가 정상적으로 설치되었는지 확인합니다. (출력 결과: Hello again)

docker run node-base node -e "console.log('Hello again')"

 

9. 사용이 끝난 컨테이너를 삭제합니다

docker rm -f base-container

베이스 이미지란?

베이스 이미지는 다른 이미지를 빌드할 수 있는 기반이 되는 이미지입니다.
어떤 이미지는 기본 이미지로 사용될 수도 있지만, 일부 이미지는 애초에 빌드 블록(building block)으로 설계되어, 특정 애플리케이션을 위한 시작점 역할을 합니다.

위에서 만든 node-base 이미지는 그 자체로는 특별한 기능이 없지만, Node.js 환경을 갖춘 기반 이미지로서 다른 애플리케이션을 만들 때 활용할 수 있습니다.


2단계: 애플리케이션 이미지 만들기

이제 node-base를 기반으로 새로운 애플리케이션 이미지를 만들어 봅시다.

1. node-base 이미지에서 새로운 컨테이너를 실행합니다.

docker run --name=app-container -ti node-base

 

2. 컨테이너 내부에서 app.js라는 파일을 생성합니다.

echo 'console.log("Hello from an app")' > app.js

 

3. 애플리케이션을 실행하여 동작을 확인합니다. (출력 결과: Hello from an app)

node app.js

 

4. 새로운 터미널에서 아래의 명령어를 입력하여 컨테이너의 변경사항을 새로운 이미지 레이어로 저장합니다. 이 명령어는 새로운 구성 정보를 추가할 뿐만 아니라, 컨테이너 실행 시 기본적으로 node app.js가 실행되도록 설정합니다.

docker container commit -c "CMD node app.js" -m "Add app" app-container sample-app

 

5. 이미지의 변경된 레이어들을 확인합니다.

docker image history sample-app

------
출력 예시
------
IMAGE          CREATED              CREATED BY                                      SIZE      COMMENT
c1502e2ec875   About a minute ago   /bin/bash                                       33B       Add app
5310da79c50a   4 minutes ago        /bin/bash                                       126MB     Add node
2b7cc08dcdbb   5 weeks ago          /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>      5 weeks ago          /bin/sh -c #(nop) ADD file:07cdbabf782942af0…   69.2MB
<missing>      5 weeks ago          /bin/sh -c #(nop)  LABEL org.opencontainers.…   0B
<missing>      5 weeks ago          /bin/sh -c #(nop)  LABEL org.opencontainers.…   0B
<missing>      5 weeks ago          /bin/sh -c #(nop)  ARG LAUNCHPAD_BUILD_ARCH     0B
<missing>      5 weeks ago          /bin/sh -c #(nop)  ARG RELEASE                  0B

 

6. 마지막으로 생성된 sample-app 이미지를 실행해 보겠습니다. 기본 명령어를 지정했기 때문에, 아래의 명령어로 다음과 같은 Node 프로그램의 출력을 확인할 수 있습니다: Hello from an app

docker run sample-app

 

 

7. 사용이 끝난 컨테이너를 삭제합니다.

docker rm -f app-container

 

다음 단계

앞서 설명했듯이, 실제 환경에서는 직접 docker container commit을 사용하기 보다는, Dockerfile을 통해 이미지 빌드를 자동화하는 것이 일반적입니다. 다음 글에서 Dockerfile을 활용한 자동화된 이미지 빌드에 도전해 보세요! 🚀

 

원문

https://docs.docker.com/get-started/docker-concepts/building-images/understanding-image-layers/

 

Understanding the image layers

This concept page will teach you about the layers of container image.

docs.docker.com