임대일

4.1 도커(Docker) 이미지 빌드: 이미지와 레이어(Layer) 본문

도커/개발자를 위한 쉬운 도커

4.1 도커(Docker) 이미지 빌드: 이미지와 레이어(Layer)

limdae94 2024. 6. 29. 11:14
 

개발자를 위한 쉬운 도커 강의 | 데브위키 - 인프런

데브위키 | 현업 개발자가 도커를 사용한 경험을 녹여낸 새로운 커리큘럼으로 기존 교재 및 강의와 차별된 강의를 제공합니다. 단순한 명령어 사용법이 아닌 도커를 왜 사용해야하는지 대한 근

www.inflearn.com

 

1. 이미지 레이어

image Layer pull

 

이미지는 컨테이너를 실행하기 위한 읽기 전용 파일이다. 도커 이미지는 효율적으로 운용하기 위해 Layered File System으로 구성되어 있다. 여러 개의 층으로 구성되어 있는 것에서 한 개의 층을 레이어라고 부른다. 흔히 레이어드 티셔츠나 레이어드 맨투맨처럼 여러 개의 레이어로 구성되어 있다는 의미와 동일하다.

 

위의 그림을 살펴보면 여러 풀이 동작되는데 각 풀이 레이어이다. 하나의 이미지를 여러 개의 레이어로 나누는 이유는 재사용하기 편리하고, 공간을 효율적으로 사용하여 스토리지와 네트워크 사용량을 줄일 수 있다. 이 방식이 바로 Layered File System이다.

 

조경, 전기, 토목, 구조 설계도

건축 도면 중에서 조경, 전기, 토목, 고조 도면을 생각해보자. 건축에 변경 사항이 발생하거나 또 다른 설계도에서 재활용이 유리하다.

 

전기 설계도만 서로 다르다.

이처럼 설계도의 겹치는 부분은 종이 사용량도 줄이고 보관 공간도 줄일 수 있다. 즉 레이어 구조는 데이터 전송에 있어서도 유리하다.

 

index.html 파일만 서로 다른 nginx image

OS 위에서 Nginx설치와 함께 필요한 파일들도 설치된다. 이어서 새로운 두 번째 Nginx를 설치한다고 가정했을 때 이전의 Nginx와 비교하여 새로운 소프트웨어가 추가된 부분만 설치하면 되는 것이다. 그리고 index.html 내용을 변경한다고 가정할 때 Nginx는 모두 동일하기 때문에 동일한 레이어를 사용하게 된다. 따라서 index.html이 포함된 레이어만 서로 다르다면 이전 레이어는 서로 공유해서 재사용하여 효율적인 운용이 가능하다.

 

nginx container1 index.html

docker run --name 으로 명령을 실행하면 이미지의 가장 마지막 레이어 위에 새로운 읽기/쓰기 레이어가 추가된다. 추가된 읽기/쓰기 레이어를 컨테이너 레이어라고 한다. 어플리케이션에서 로그가 쌓이거나 컨테이너가 실행 중에 변경이 되는 모든 사항은 바로 컨테이너 레이어에 저장된다.

 

이미지 레이어는 읽기 전용 레이어로 컨테이너 레이어와 전혀 다르다. 왜냐하면 이미지 레이어는 실행 중에 절대로 쓰기가 불가능하기 때문에 읽기 전용 레이어이다.

nginx container1, container2 index.html

두 개의 컨테이너가 동일한 ImageA 를 읽는다고 가정할 때 Container1, Container2 는 동일한 레이어를 거치게 된다. 따라서 저장 공간의 효율성을 가질 수 있다.

 

nginx container1, container2, container3 index.html

Container3 의 경우는 index.html 레이어만 다르고 나머지 레이어는 모두 동일하게 접근한다. 즉, 이미지 레이어 전부를 공유하거나 일부분을 공유할 수 있다. 전체 공간을 복사하지 않아도 되기 때문에 빠르게 실행이 가능하고 가용성이 우수하다.

 

Image Layer, Container Layer

설계도와 마찬가지로 하나의 이미지로 컨테이너를 수십 개 실행해도 근본적인 기능을 모두 동일하고 읽기/쓰기 레이어에는 고유한 값이 쌓이게 될 것이다.

2. image history

docker image history 이미지명

docker image history 이미지명 # 이미지의 레이어 이력 조회

이미지의 레이어 이력 조회 실습을 위해 세 개의 nignx 이미지를 다운 받도록 한다.

 

docker pull devwikirepo/hello-nginx, config-nginx, pre-config-nginx
docker pull devwikirepo/hello-nginx, config-nginx, pre-config-nginx

docker pull devwikirepo/hello-nginx
docker pull devwikirepo/config-nginx
docker pull devwikirepo/pre-config-nginx

위 그림처럼 nginx 이미지를 다운 받은 후에 다시 새로운 리포지토리명으로 config-nginx를 다운 받을 때 이미 존재한다는 각 풀을 확인할 수 있다. 이처럼 이미 존재하는 nginx 이미지 레이어를 새로 다운받는 것이 아니라 공유하여 사용하게 되는 것이다.

 

docker image history devwikirepo/hello-nginx

 

docker image history devwikirepo/config-nginx

 

docker image history devwikirepo/pre-config-nginx

세 개의 명령 실행 결과를 살펴보면 index.html 실행 순서가 다르다는 것을 확인할 수 있다.

 

docker image inspect devwikirepo/hello-nginx

RootFS 안에 각 이미지 레이어마다 SHA256 으로 암호화된 고유한 해시값을 확인할 수 있다. 중요한 것은 레이어가 고유한 ID 해시값을 갖고 있다는 것이다.

 

nginx:1.24.0, hello-nginx, config-nginx, pre-config-nginx

3개의 이미지 모두 nginx 1.24.0 버전으로 생성되어서 nginx 이미지 자체의 해시값과 동일하다. 각 레이어마다 해시값이 다른 것을 nginx 이미지 자체의 해시값과 다르다고 오해하지 말자.

 

두 번째 hello-nginx 이미지는 index.html 이 수정된 이미지이다. 따라서 Nginx 기본 이미지에 레이어 한 줄이 추가된다. config 이미지는 nginx.conf 가 수정된 nginx 이미지이기 때문에 config 이미지 레이어에서 한 줄이 추가 된 것이다. 마지막 pre-config 는 nginx.conf 와 index.html 를 모두 수정하여 다른 이미지들과 모두 레이어 해시값이 다른 것을 확인할 수 있다.

자세히 살펴보면 이미지의 레이어는 이전 파일에서 변경된 사항을 저장하기 때문에 결과적으로는 두개가 동일한 내용이더라도 레이어를 구성한 순서가 다르다면 전혀 다른 이미지가 되는 것이다.

 

이렇게 동일한 Nginx 1.24.0 이미지들은 모두 같은 Nginx 이미지를 공유하게 된다. 이 레이어 구조가 없다면 모든 이미지들이 투명하게 표현된 모든 레이어를 별도로 저장해야 할 것이다. 따라서 layered File System은 네트워크 속도와 스토리지에서 큰 장점이다.

 

Image Layer: Layering, Copy-on-Wirte(COW) 전략

레이어에서 index.html은 총 세 개가 되는 것이다. 이 중에서 가장 최근에 변경이 발생된 Container Layer에 저장된 index.html이 실제 파일의 내용으로 사용이 되는 것이다. 새로운 레이어는 이전 레이어에 영향을 주지 않고, 자신의 레이어에 수정할 내용을 카피하고 수정해서 사용하는 것이다. 즉, 이미지의 일관성을 가지게 되면서 불변성을 만족할 수 있다.

 

Immutable Layer, Caching

 

따라서 동일한 이미지를 사용하는 컨테이너는 모두 동일한 파일 시스템을 사용하는 것을 보장할 수 있다. 이미지를 생성할 때 캐시에 보관한다면 빠르게 이미지를 가용할 수 있다. 캐시는 실무 파트에서 더 자세히 다루자.

 

  1. Layering: 각 레이어는 이전 레이어 위에 쌓이며, 여러 이미지 간에 공유될 수 있다. 레이어 방식은 중복 데이터를 최소화하고, 빌드 속도를 높이며, 저장소를 효율적으로 사용할 수 있게 해준다.
  2. Copy-on-Write (COW) 전략: 다음 레이어에서 이전 레이어의 특정 파일을 수정할 때, 해당 파일의 복사본을 만들어서 변경 사항을 적용한다. 따라서 원래 레이어는 수정되지 않고 그대로 유지된다.
  3. Immutable Layers (불변 레이어): 이미지의 각 레이어는 불변으로, 한 번 생성되면 변경되지 않는다. 따라서 이미지의 일관성을 유지하고, 여러 컨테이너에서 안전하게 공유할 수 있다.
  4. Caching (캐싱): 레이어를 캐시하여, 이미 빌드된 레이어를 재사용할 수 있다. 이는 이미지 빌드 시간을 크게 줄여주며, 같은 레이어를 사용하는 이미지에서 효율적으로 작동한다.