본문 바로가기

도커와 쿠버네티스

[2주차] Part 2: 이미지는 읽기 전용(read-only) 파일일 뿐이다

본 게시글은 유데미(udemy.com)의 < 【한글자막】 Docker & Kubernetes : 실전 가이드 > (Maximilian Schwarzmüller) 강의를 수강한 후 내용을 정리한 것입니다.

 


 

 

 

도커 컨테이너에 담긴 소스 코드의 일부를 수정하고 싶다.

이 코드를 수정한 다음 컨테이너에 새로 반영하고 싶었기 때문에 컨테이너를 중단하고 다시 시작했다.

어라, 그런데 여전히 아까랑 똑같은 결과다. 왜 그런 걸까?

 

그 이유는, 도커 image는 소스코드의 스냅샷(snapshot)을 찍는 것과 같기 때문이다.

즉 image는 한번 빌드한 이후로는 기본적으로 외부에서 더 이상 바꿀 수 없으며 끝난(locked and finished) 상태가 된다.

 

 

 

 

도커 이미지는 layer로 구성되어 있다

Dockerfile에서 명령어의 순서는 중요하다("The order of Dockerfile instructions matters").
각 명령어는 한 layer에 대강 대응한다고 보면 된다. (공식 문서도 꼼꼼히 읽어볼 것: https://docs.docker.com/build/guide/layers/)

 

image에 수정이 가해졌다고 다시 처음부터 쌩으로 build하는 건 중복이 많고 비효율적인 작업이다.

수정을 하지 않은 똑같은 부분은 그대로 저장(=cache)해두었다가 활용하고, 바뀐 부분만 업데이트해서 빌드하면 더 빠를 것이다.
그렇기 때문에 Dockerfile에서 image를 빌드하는 과정은 분명히 순서가 존재(=layer 구조)한다.

 

 

 

 

 

 

 

 

어떤 코드를 수정했다고 하자.

수정한 layer 다음의 모든 layer는 사실 그대로인데, 이 layer들을 처음부터 다시 rebuild하는 건 비효율적인 것 같다.
이 문제를 어떻게 해결할 수 있을까?

다시 node image의 Dockerfile로 돌아가보자.

 

 

 

 

 

비효율적인 방식 (Dockerfile로 image build하기)

 

FROM node

WORKDIR /app

COPY . /app

RUN npm install

EXPOSE 80

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

 

 

코드 일부를 수정하면 COPY 명령어의 layer부터 다시 build해야 한다.
그러면 코드만 바뀌었을 뿐 사실 node 패키지는 다시 새로 설치(npm install )할 필요가 없는데,

RUN 명령어는 COPY 이후의 layer에 해당하니 npm을 새로 설치하게 된다. 분명 불필요한 작업이다.

이 부분을 어떻게 optimization해야 할까?

 

 

 

 

개선된 방식 (Dockerfile로 image build하기)

Dockerfile에서 명령어 순서를 좀 바꿔주었다.

우선 package.json 파일을 복사해서 npm을 설치하는 데 꼭 필요한 의존성 패키지를 준비해놓고,

그 다음에 npm을 설치한 다음

로컬에 있는 모든 파일을 컨테이너에 복사한다.

 

FROM node

WORKDIR /app

COPY package.json /app

RUN npm install

COPY . /app

EXPOSE 80

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

 

이렇게 하면

 

1) RUN 명령어는 COPY 명령어 이전에 있기 때문에,

COPY 명령어(COPY . /app)의 layer에서 수정이 되어 cache가 invalidate되어도

이미 RUN npm install 파트는 지나왔다(cache를 활용).

즉 불필요하게 npm을 다시 설치하지 않는다.

 

2) 이 Dockerfile에 대한 캐시가 없더라도

COPY package.json /app 에서 npm을 설치하기 위한 패키지를 package.json으로 가져오기 때문에

아무런 문제 없이 npm install을 실행할 수 있다.