Image-Layer

namkun·2022년 4월 30일
0

Docker & Kubernetes

목록 보기
4/16

만약 우리가 이미지를 만들고 난 뒤, 소스코드를 수정할 일이 있다면 어떻게 해야할까?

답은 간단하다.

이미지를 다시 빌드하고, 그걸 실행하면 된다.

이미지는 기본적으로 수정에 대해 잠겨있고, 빌드되면 그 이상 무언가를 할 수 없다.

그러니까 이미지는 빌드가 완료되면 'Read-Only'인 것이다.

자 그럼 우리는 한번 코드를 수정하고, 그게 반영되는걸 보기위해서 이미지를 재빌드 해본다.

우선 도커파일을 하나 만들어본다.

FROM node

WORKDIR /app

COPY . /app

RUN npm install

EXPOSE 80

CMD ["node", "server.js"]

간단하게, node 서버를 띄우는 앱이다.

이미 빌드를 한 번 해봤던 도커파일이기에, 재빌드를 해보면 어떻게 진행되는지 볼 수 있을 것이다.

$ docker build .
[+] Building 46.4s (9/9) FINISHED
 => [internal] load build definition from Dockerfile                                0.0s
 => => transferring dockerfile: 144B                                                0.0s
 => [internal] load .dockerignore                                                   0.0s
 => => transferring context: 2B                                                     0.0s
 => [internal] load metadata for docker.io/library/node:latest                     41.8s
 => [1/4] FROM docker.io/library/node@sha256:e5b7b349d517159246070bf14242027a9e220  0.0s
 => [internal] load build context                                                   0.0s
 => => transferring context: 1.25kB                                                 0.0s
 => CACHED [2/4] WORKDIR /app                                                       0.0s
 => [3/4] COPY . /app                                                               0.1s
 => [4/4] RUN npm install                                                           4.2s
 => exporting to image                                                              0.2s
 => => exporting layers                                                             0.2s
 => => writing image sha256:9f9a1ee78f6323a1b209294bc3f24f99f81ce87da750fd235684a2  0.0s

처음 이미지를 빌드했을때에 비해서 굉장히 빠르게 빌드되는 것을 확인할 수 있다.

왜일까?

저 위의 메세지를 보면 우리는 CACHED(아니면 using cache)라는 메세지를 볼 수 있다.

왜냐면 우리가 변경한건 오직 애플리케이션의 소스코드이지, 도커파일이라던가 그런걸 변경한건 하나도 없기에, 도커가 docker build .이라는 명령어의 결과가 그 전과 동일하다는 것을 인식했기 때문이다.

도커는 이미지를 빌드할 때마다 모든 명령어의 결과를 캐시하고, 이미지를 다시 빌드할 때 명령을 다시 실행할 필요가 없으면 이렇게 캐시된 결과를 사용한다.

어떻게 이런 것이 가능할까?

layer

이러한 것들은 모두 이미지의 레이어 기반으로 이뤄지는데, 위의 과정이 어떻게 이뤄지는지 한 번 알아보자.

도커 이미지는 레이어와 메타정보로 구성되어있다.

docker inspect 명령어를 통해서 도커 이미지가 어떤 레이어로 구성되었는지 알 수 있다.

도커의 이미지 레이어는 앞에서 말했듯 Read-Only이나, 컨테이너 레이어는 Read, Write 모두 가능하다. 왜냐하면 컨테이너가 작업하는 파일을 저장하기 위해서이다.

이러한 레이어들은 Dockerfile을 빌드하면 동시에 명령어를 통해서 생성되며, 캐시된다.

그러니, 위에서 말한 모든 명령어의 결과를 캐시 한다는 것은 레이어를 캐시한다는 말과 동일하다.

이렇게 캐시된 레이어들을 우리는 재빌드할때 사용하여, 이미지를 빌드하는 속도를 최소한으로 줄일 수 있다.

rebuild시의 재생성 되는 layer

위에서 봤던 이미지를 재빌드 했을때 나오는 메세지를 다시 보자.

=> CACHED [2/4] WORKDIR /app                                                       0.0s
=> [3/4] COPY . /app                                                               0.1s
=> [4/4] RUN npm install                                                           4.2s

자 앞서 말했듯, 이미지를 빌드하면 명령어들은 레이어로 캐시된다고 했고, 이는 추후 리빌드시에 재사용된다고 하였다.

그러나 정작 캐시된 레이어로 사용된건 WORKDIR /app 명령어뿐이고 나머지는 다시 레이어를 생성하였다.

왜일까?

도커는 npm install 이 이제 이전과 동일한 결과를 내뱉을 것인지에 대한 그 여부를 알 수 없기에, 그 뒤의 후속 명령어(레이어)도 같이 실행하는 것이다.

결국 앞의 한 레이어가 변경될 때마다, 모든 후속레이어에 대한 결과 역시 어떻게 될 지 모르기에 전부 다시 생성된다.

그렇기에 우리는 Dockerfile 작성 시에 이러한 것들을 고려해서 작성해야 이미지를 재사용할 때, 최고의 효율을 얻을 수 있을 것이다.

Dockerfile re-factoring

자, 위에서 제시한 예시를 다시 생각해보자.

단순하게 소스코드만 변경했고, 이를 위해서 이미지를 재빌드 했다.

우리는 따로 노드 애플리케이션에 종속성에 영향을 미치는 package.json이라는 파일을 수정하지도 않았다.

그런데 위에서 작성된 도커파일을 이미지로 빌드했을때를 확인해보면, 빌드할 때마다 npm install이라고 종속성을 매번 설치하고 있음을 알 수 있다. 왜냐하면 위의 명령어(레이어)가 코드의 변경에 의해 재생성되기 때문이다.

매번 종속성을 설치한다는건 아주 비효율적인 일이다. 시간도 오래걸리고.

그러면 미리 종속성을 관리하는 package.json을 옮기고, npm install을 통해서 종속성을 설치한 뒤에 소스코드를 옮기면 해결될 일이다.

FROM node

WORKDIR /app

COPY package.json /app

RUN npm install

COPY . /app

EXPOSE 80

CMD ["node", "server.js"]

자 이렇게 변경하였다.

그러면 이제 우리가 소스코드를 변경하고 복사하더라도, 종속성을 매번 설치하는 일은 없을 것이다.

한번 먼저 빌드한 뒤에 이미지 재빌드를 해보면?

...
 => CACHED [2/5] WORKDIR /app                                                                                             0.0s 
 => CACHED [3/5] COPY package.json /app                                                                                   0.0s 
 => CACHED [4/5] RUN npm install                                                                                          0.0s 
 => [5/5] COPY . /app                                                                                                     0.0s
 => exporting to image                                                                                                    0.1s
 => => exporting layers                                                                                                   0.1s 
 => => writing image sha256:a79f50098489326f784eef6b51f66fc66dea00bc40ab5fba34672685dedd2c13                              0.0s

npm install이 cache된 결과를 사용하여 굉장히 빠르게 지나간 것을 알 수 있다.

자 이제 이미지레이어에 대해서 이해를 했으니, 앞으로 Dockerfile을 작성할 때 어느부분을 신경써가며 작성해야하는지를 알 수 있을 것이다.


참고

profile
개발하는 중국학과 사람

0개의 댓글