본문 바로가기
Code/개발지식

Dockerfile 작성 시 캐싱문제 방지하기

by 코드포휴먼 2021. 4. 20.

Dockerfile를 통해서 도커 이미지를 빌드할 때 패키지 관리 이슈가 생길 수 있다. 

알아보니 Dockerfile의 레이어(Layer)와 캐싱 문제를 확인할 수 있었다.

 

우선, 이미지 레이어 캐싱을 통해 얻을 수 있는 장점은 재사용에 의한 빌드 시간 단축이다.

Dockerfile에 정의된 명령문을 순서대로 실행하면서 이미지가 빌드될 때 레이어가 만들어지는데,

만약 특정 줄에 해당하는 명령어와 이전 명령어들이 같다면 동일한 레이어로 판단하기 때문에 캐싱되어 있는 부분을 가져온다.

이미 생성된 레이어가 캐시되어 다시 사용되기 때문에 빌드 시간을 줄일 수 있는 것이다.

공식 홈페이지 문서의 Dockerfile 작성 안내에서는 아래처럼 말하고 있다.

A Docker image consists of read-only layers each of which represents a Dockerfile instruction. The layers are stacked and each one is a delta of the changes from the previous layer.

 

 

그런데 새로운 이미지 빌드 시, 파일이나 패키지가 변경되었음에도 처음 캐싱된 레이어의 정보로 인해 이전의 것이 이미지에 포함되는 문제가 발생한다.

이유는 Dockerfile에서는 명령어 한줄 한줄을 레이어로 판단하며 해당 레이어 별로 캐싱을 진행하기 때문에 그렇다.

(레이어들은 각각 독립적으로 저장되며, docker image inspect 명령어를 실행하여 반환되는 해시값으로 호스트 머신 내 어딘가 실제 레이어 내용이 저장된 것을 찾을 수 있다.)

 

 

따라서 처음부터 Dockerfile을 작성할 때 이러한 캐싱 문제를 염두해두는 게 좋다.

캐싱 문제에 있어서 캐시 가능한 단위를 확인하는게 좋은데, Dockerfile에 정의된 모든 명령문이 레이어가 되는 건 아니다.

RUN, ADD, COPY 이 3가지 단계만이 레이어로 저장되고,

CMD, LABEL, ENV, EXPOSE 등과 같이 메타 정보를 다루는 부분은 임시 레이어로 생성되지만 저장되지 않아 도커 이미지 사이즈에 영향을 주지 않는다.

 

 

내가 사용한 대처방법은 아래와 같다.

첫째, 도커 이미지 빌드 시 캐시를 사용하지 않도록 —no-cache 옵션을 이용한다.

 

둘째, 패키지 매니저로 패키지를 설치할 때 업데이트(update)와 설치(install)를 한 레이어로 생성한다.

항상 패키지 인덱스 정보를 업데이트하고, 동일한 RUN 실행단위에서 패키지를 설치하는 게 좋다고 한다. (update & install)

이렇게 하면 캐시 가능한 하나의 유닛이 될 뿐더러 오래된 패키지를 설치할 위험도 사라진다.

 

또한, 도커 레이어 개수를 줄이는 것은 최적화 측면에서 도움이 된다.

과거 도커 버전에서는 이미지 레이어 개수가 성능에 영향을 줬지만 이제는 그렇지 않다.

그래도 여러 RUN 구문으로 명령을 분리하는 것보다 체이닝(chaining)을 통해 레이어를 줄이면 Dockerfile의 가독성과 유지보수가 용이해진다.

 

예) 개선 전

RUN apt-get update
RUN apt-get -y install git
RUN apt-get -y install locales
RUN apt-get -y install gcc

예) 개선 후

RUN apt-get update && apt-get install -y \
    gcc \
    git \
    locales

 

 

추가적으로 아래 출처에 명시한 링크에서 Dockerfile을 현명하게 작성할 수 있는 여러 팁들을 읽어보면 좋다.


출처

블로그 twpower https://twpower.github.io/247-file-download-issue-caused-by-layer-cache-in-docker-build

블로그 manofbell https://velog.io/@manofbell/Dockerfile-%EB%AA%A8%EB%B2%94-%EC%82%AC%EB%A1%80-%EC%86%8C%EA%B0%9C

블로그 jonnung.dev/docker/2020/04/08/optimizing-docker-images/

댓글