Docker & Container

[Docker] image를 구성하는 image layer

아무일도없었다 2023. 4. 23. 16:54

Docker image & conatiner

 

Image의 정의

Container라는 독립된 환경에서 서비스가 실행 가능하도록 필요한 요소를(서버 환경, 실행 파일, 라이브러리, 구조 등...) 하나의 패키지 형태로 묶는 형태

 

Container의 정의

소프트웨어 서비스를 실행하는데 필요한 요소를 포함하는 경량 패키지

 

 

 

 

Docker의 image 특정 환경과 파일, 라이브러리 등을 실행할 수 있는 Container를 생성하기 위한 파일이다. (vm에서는 iso 파일에 해당되는 파일이다.)

 

image만 있으면 container를 계속 생성할 수 있으며, image 하나를 가지고 여러 container들을 생성할 수 있다.

 


 

Image Layer

 

Image와 Layer

 

Image는 container를 실행하기 위한 요소들을 효율적으로 관리하기 위해 layer라는 구조를 사용한다.

 

Container를 생성하기 위해 OS부터 필요한 library와 실행파일들을 image에 모두 담는데 이 모든 것들을 하나의 파일로 관리하기에는 너무 비효율적이기 때문이다. (명령어 단 한 줄 차이로 image를 os부터 새로 build 하기에는 시간과 디스크용량이 너무 아까울 것이다.)

 

 

그렇다면 layer로 이루어진 구조에서는 어떻게 동작하는가?

 

 

만약 CentOS 버전 7 환경에서 jdk1.8을 사용하는 java로 개발된 프로그램을 실행할 수 있는 image가 있다고 가정한다면 아래와 같은 그림으로 표현될 수 있다.

 

CentOS7에서 jdk1.8을 사용하는my_app.jar를 실행하는 image 구조

 

위의 image를 잘 사용하다가 my_app.jar에서 문제가 발생하여 new_my_app.jar로 바꾼 image를 새로 만든다면 아래와 같은 구조가 될 것이다.

 

my_app.jar → new_my_app.jar로 변경

 

my_app.jar에서 new_my_app.jar로 변경이 된다면 image를 구성하는 파일 전체를 수정하는 게 아닌 마지막으로 수정된 layer만 변경되는 것을 확인할 수 있다.

 

그렇다면 jdk 1.8을 jdk 1.7로 변경한다면 중간에 있는 layer만 변경이 될까?

 

안타깝지만 답은 불가능이다.

 

이유는 layer의 구조에 있는데 layer는 기존 이미지에서 변경된 사항을 저장하는 구조로 쌓이기 때문이다.

 

사실 위의 그림에서는 CentOS:7에서 jdk 1.8을 사용하는 my_app.jar를 실행하는 image 파일 하나로 표현했지만 실제로는 3개의 image 파일이 존재하고 있다.

 

 

CentOS 버전 7의 image(centos)를 기반으로 jdk 1.8 버전을 설치한 layer를 추가한 image(centos + jdk)가 만들어지고, 그 image(centos + jdk)를 기반으로 jar 파일을 올려서 실행하는 layer를 추가한 image(centos + jdk + jar)를 만든 것이다.

 

따라서 jdk를 변경한다면 centos 기반 image(layer)는 동일하기 때문에 변하지 않지만, 중간의 image(centos + jdk)가 변경될 것이고, 이를 기반으로 만든 image(centos + jdk + jar)에서 또한 같이 변경되는 것이다. (아래 그림 참고)

 

기존과의 변경점을 저장한 Layer

 

 

정리하자면 Layer는 Stack처럼 기존의 Layer에서 변경점을 저장하는 구조이며, 만약 중간 부분의 Layer 변경 시 이를 기반으로 만들어 올린 Layer 전체가 변경된다는 점이다.

 

위의 그림에서는 Image(centos + jdk + jar)로 표현했지만, Image[ (((centos) + jdk) + jar) ] 가 조금 더 정확한 표현이다.

 

 

Docker에서는 docker inspect 명령어를 사용하면 맨 아래쯤에 있는 Layers 항목을 통해 해당 image의 layer를 확인할 수 있다.

 

# docker inspect 6ae02af85788

     (생략)

        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02",
                "sha256:c86f8b31680d68d23dd1bf82fb9bdb5a9988e51466534aa9305fbca2f2ca50b4",
                "sha256:37a7bdb99587567593329e11a4171b58ecd66bf2571690620cad3e5f99e530f4",
                "sha256:b60fdd25b8ed67d15328b392b2b58a93db999116639357fa7ba72feba5096667",
                "sha256:07b542192166464ab9f05c909d5027de6bc9b06f9b115c775b84d3c6250f30c4",
                "sha256:07b542192166464ab9f05c909d5027de6bc9b06f9b115c775b84d3c6250f30c4"
            ]
        },
        
     (생략)

 

이러한 image layer 구조를 사용한 덕분에 image를 개발할 때 완전히 새로 만드는 것이 아닌 기존의 layer를 가져와서 변경점만 추가로 저장하는 방식으로 효율을 끌어올렸다.

(예를 들어 centos 기반의 postgresql을 사용하는 여러 image를 개발하는 경우 [ centos + postgresql ] 의 image layer를 가져다가 개발 시 변경점만 추가하기 때문에 굉장히 빠른 build가 가능해진다.)

 

 

반응형