이 글은 [2024 NEW] 개발자를 위한 쉬운 도커 강의를 듣고 작성한 글입니다! 모든 강의자료 이미지 출처는 해당 강사님께 있습니다.
레이어(Layer)
이미지는 컨테이너를 실행하기 위한 읽기 전용 파일이다. 도커 이미지는 저장소를 효율적으로 사용하기 위해 Layered File System 으로 구성되어 있다. 레이어는 하나의 층을 말한다. 이미지는 여러 개의 레이어로 구성되어 있다.
로컬 저장소의 이미지가 없는 것을 확인하고 Docker hub에서 이미지를 다운로드 받는다. nginx라는 하나의 이미지를 다운받는 과정에서 pull이 여러 번 실행되는 것을 볼 수 있는데, 하나의 pull이 하나의 layer라고 생각하면 된다.
굳이 하나의 이미지를 왜 여러개의 레이어로 구성했을까? 레이어 구조가 재사용 하기 유리한 구조이기 때문이다. 공간을 효율적으로 사용할 수 있어 이미지 전송하고 저장할 때 스토리지와 네트워크 사용량을 줄일 수 있다.
Nginx 이미지 설계 예시
이미지의 레이어는 바로 직전 레이어에서 변경된 내용만 저장된다. 서버에 간단한 페이지를 출력하는 nginx를 설치한다고 생각해보자. nginx를 구성하는 단계는, OS를 설치하고, nginx를 설치하고 nginx를 설치하고 Index.html 파일을 수정하는 것으로 이루어져 있다.
기존 레이어에서 변경되는 것들은 기존의 레이어를 수정하는 것이 아니라 기존 레이어 위에 변경된 내용들이 새로운 레이어로 저장된다. 이미지에서 한 번 저장된 레이어는 변경할 수 없다. 변경사항을 저장하려면 새로운 레이어로 저장해야 한다. ImageB에서, ImageA와의 차이가 4번 레이어의 보여주는 html 파일 내용만 다르다고 했을 때, 기존에 있는 3개의 레이어는 그대로 재사용하고 변경된 레이어만 추가한다. ImageA와 ImageB는 3개의 레이어는 공통으로 사용하고 1개의 레이어만 각각 사용하는 구조가 된다. 레이어의 이미지는 순차적으로 쌓인다.
docker run 으로 컨테이너를 실행하면, 이미지의 가장 마지막 레이어 위에 새로운 읽기/쓰기 전용 레이어가 추가된다. 이 레이어는 컨테이너 레이어라고 한다. 이미지의 레이어는 수정이 불가능한 읽기 전용 레이어이다. 이미지의 레이어와 컨테이너의 레이어는 역할이 완전 다르다. 이미지의 레이어는 컨테이너를 실행하기 위한 save point 역할을 하고, 컨테이너 레이어는 이미지를 컨테이너로 실행하고 프로세스가 변경하는 내용을 기록하는 레이어이다. 컨테이너 레이어는 쓰기가 가능한 읽기/쓰기 레이어로, 컨테이너 실행중에 변경되는 내용만 기록한다.
ImageA로 Contianer1과 Container2를 실행하면 각각 Container1의 읽기/쓰기 레이어와 Container2의 읽기/쓰기 레이어가 생성된다. Container1과 Container2는 이미지가 같기 때문에 동일한 읽기 전용 레이어를 공유한다. 실제로 컨테이너를 실행할 때 전체의 레이어를 복사하는 것이 아니라, 읽기 전용 레이어인 이미지 위에 새로운 컨테이너 레이어만 추가하는 것이다.
ImageB로 Container3를 실행하면 Container1, Container2와 레이어3번까지만 공유한다.
정리하자면, 모든 컨테이너는 자신만의 읽기/쓰기 레이어 한 장을 가진다. 컨테이너를 만들 때 사용된 이미지에 따라 이미지의 읽기 전용 레이어의 전체를 공유하거나, 일부를 공유할 수 있다. 컨테이너를 실행할 때 전체 공간을 복사하지 않아도 컨테이너를 빠르게 실행할 수 있다. 컨테이너가 사용하는 공간도 최소로 사용할 수 있다.
이미지를 다운받고 이미지의 레이어를 비교하는 실습
3개의 이미지를 다운받는다.
docker pull devwikirepo/hello-nginx
docker pull devwikirepo/config-nginx
docker pull devwikirepo/pre-config-nginx
이미지를 잘 다운 받은 것을 확인한다.
docker image ls
이미지 레이어를 구성한 순서를 확인하기 위해 다음 docker image history 명령어를 사용한다.
docker image history devwikirepo/hello-nginx
docker image history devwikirepo/config-nginx
docker image history devwikirepo/pre-config-nginx
이미지의 메타데이터를 확인할 때 docker image inspect 명령어를 사용했는데, 이 명령어를 통해 이미지 레이어의 해시값도 볼 수 있다.
docker image inspect devwikirepo/hello-nginx
docker image inspect devwikirepo/config-nginx
docker image inspect devwikirepo/pre-config-nginx
hello-nginx는 기본 nginx 이미지에 index.html을 수정한 이미지이다. config-nginx는 기본 nginx 이미지에서 index.html 파일을 hello-nginx와 같이 수정하고, nginx.conf 를 수정한 이미지이다. pre-config-nginx는 nginx.conf 파일을 수정하고 index.html 파일을 수정한 이미지이다.
이미지의 해시값은 sha256 알고리즘으로 생성되며, 각각의 레이어의 변경사항을 암호화 한 값이다. 이미지 레이어의 고유한 해시값을 통해서 다른 레이어와 구분된다.
config-nginx와 pre-config-nginx 의 차이는 nginx.conf 파일과 index.html 파일의 수정한 순서의 차이이다. 순서가 다르면 고유한 값으로 저장된다.
이미지 레이어 정리
Layering : 각 레이어는 이전 레이어 위에 쌓이며, 여러 이미지 간에 공유될 수 있다. 레이어 방식은 중복 데이터를 최소화하고, 빌드 속도를 높이며, 저장소를 효율적으로 사용할 수 있다.
Copy-on-Write 전략 : 다음 레이어에서 이전 레이어의 특정 파일을 수정할 때, 해당 파일의 복사본을 만들어서 변경 사항을 적용한다. 이렇게 함으로써 원래 레이어는 수정되지 않고 그대로 유지된다.
Immutable Layers(불변 레이어) : 이미지의 각 레이어는 불변으로, 한 번 생성되면 변경되지 않는다. 이렇게 함으로써 이미지의 일관성을 유지하고, 여러 컨테이너에서 안전하게 공유할 수 있다.
Caching (캐싱) : 레이어를 캐시하여 이미 빌드된 레이어를 재사용 한다. 이미지 빌드 시간을 크게 줄여주며, 같은 레이어를 사용하는 여러 이미지에서 효율적으로 작동한다.
'Docker' 카테고리의 다른 글
빌드 컨텍스트 (0) | 2024.02.20 |
---|---|
이미지 커밋과 빌드 (0) | 2024.02.20 |
이미지 레지스트리 (0) | 2024.02.19 |
컨테이너의 라이프사이클 (0) | 2024.02.17 |
이미지의 메타데이터(Metadata) (1) | 2024.02.17 |