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

각 이미지 레이어는 파일 시스템의 변경 사항(추가, 삭제, 수정)을 포함하고 있습니다. 예를 들어, 하나의 가상의 이미지를 생각해 봅시다.
- 첫 번째 레이어에서는 기본적인 명령어들과 패키지 매니저(예: apt)를 추가합니다.
- 두 번째 레이어에서는 Python 실행 환경과 패키지 관리자(pip)를 설치합니다.
- 세 번째 레이어에서는 애플리케이션의 requirements.txt 파일을 복사해 넣습니다.
- 네 번째 레이어에서는 requirements.txt에 명시된 의존성을 설치합니다.
- 다섯 번째 레이어에서는 애플리케이션의 실제 소스 코드를 복사해 넣습니다.

이와 같은 구조 덕분에, 이미지들간에 레이어를 재사용할 수 있습니다. 예를 들어, 또 다른 Python 애플리케이션을 만들고 싶다면, 기존의 Python 실행 환경을 그대로 사용할 수 있습니다. 이렇게 하면 빌드 속도가 빨라지고, 이미지를 배포하기 위한 저장 공간 및 네트워크 대역폭을 절약할 수 있습니다. 이미지 레이어는 다른 사람이 작성한 이미지의 베이스 레이어를 재사용하여, 자신의 애플리케이션에서 필요한 데이터만을 추가하여 이미지를 확장할 수 있도록 해줍니다.
레이어 쌓기(Stacking Layers)
이러한 레이어링이 가능해지는 이유는 콘텐츠 주소 지정 저장소(content-addressable storage) 및 유니온 파일 시스템(union filesystem) 덕분입니다. 기술적인 내용을 살펴보면 다음과 같이 동작합니다.
- 컨테이너 이미지를 다운로드하면, 각 레이어는 호스트 파일 시스템의 개별 디렉터리에 압축 해제됩니다.
- 컨테이너를 실행할 때, 유니온 파일 시스템이 생성되어 여러 개의 레이어가 하나의 통합된 뷰로 합쳐집니다.
- 컨테이너가 시작되면, chroot를 사용하여 컨테이너의 루트 디렉터리가 이 통합된 파일 시스템의 위치로 설정됩니다.
- 유니온 파일 시스템이 생성될 때, 실행 중인 컨테이너 전용 디렉터리도 함께 생성됩니다.
- 이를 통해 컨테이너는 자체적으로 파일 시스템을 수정할 수 있지만, 기존의 이미지 레이어는 변경되지 않습니다.
- 덕분에 동일한 이미지를 기반으로 여러 개의 컨테이너를 실행할 수 있습니다.
실습: 이미지 레이어 직접 만들기
이번 실습에서는 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
'Docker' 카테고리의 다른 글
[도커 공식문서 학습] 7. 도커 핵심 개념 정리 - 컴포즈 (0) | 2025.03.30 |
---|---|
[도커 공식문서 학습] 6. 도커 핵심 개념 정리 - 레지스트리 (0) | 2025.03.30 |
[도커 공식문서 학습] 5. 도커 핵심 개념 정리 - 이미지 (0) | 2025.03.30 |
[도커 공식문서 학습] 4. 도커 핵심 개념 정리 - 컨테이너 (0) | 2025.03.27 |
[도커 공식문서 학습] 3. 첫 번째 이미지 빌드 및 푸시 (0) | 2025.03.26 |