도커 이미지 레이어 - 3 : 빌드캐시

3-1. 빌드캐시

빌드 중 동일한 이미지 레이어가 있으면 빌드하지 않고 재사용한다.

  • 빌드 속도 향상

  • 도커 이미지레이어 저장공간 최소화


3-2. 빌드캐시 과정

첫 번째 docker build 실행

docker build 명령어를 실행하면,

  • Dockerfile의 각 명령어(Instruction)에 따라 새로운 이미지 레이어가 생성됩니다.
  • 생성된 레이어는 로컬의 레이어 저장소에 캐시 형태로 저장됩니다.
  • 이 과정을 거쳐 최종 이미지가 생성됩니다.

동일한 docker build 재실행

동일한 Dockerfile과 컨텍스트를 기준으로 다시 docker build를 실행하면,

  • 이전에 저장된 이미지 레이어가 존재하는지 확인합니다.
  • 동일한 명령어로 생성된 레이어가 있으면 다시 빌드하지 않고 그대로 재사용합니다.
  • 이로 인해 빌드 속도가 크게 향상됩니다.

3-3. 빌드캐시 확인

Dockerfile-8

FROM busybox:1.34.1
RUN echo "helloworld"

1. Dockerfile-8 빌드

캐시가 없으므로 모든 명령어에 대해 레이어를 새로 생성한다.

  • FROM → busybox 레이어
  • RUN → echo 명령을 포함한 새 레이어 생성

2. 이미지 history 확인

example:v1 이미지는 3개의 레이어로 구성되어 있다.

  • busybox 기반 이미지 레이어 2개
  • echo 명령어 기반 이미지 레이어 1개

3. Dockerfile-8 재빌드

  • Docker는 이전에 생성된 레이어와 동일한 명령어가 있는지 확인하고,
  • Cached 메시지와 함께 캐시된 레이어를 재사용한다. FROM은 이미지 레이어를 가져오는 단계이므로 Cached가 안뜬다.
  • FROM은 빌드 명령이 아니다
  • FROM은 이미지 캐시를 사용한다.

3-4. 이미지 레이어 체인과 빌드 캐시

빌드 캐시는 Dockerfile의 명령어뿐만 아니라 부모 이미지 레이어 정보도 함께 고려된다.

상위 레이어가 변경되면, 그 아래 하위 레이어의 명령어가 동일하더라도 캐시가 무효화된다.

  • 이는 Docker의 이미지 레이어가 단순한 명령어 결과뿐만 아니라, 데이터 + 부모(parent) 이미지 정보로 구성되기 때문이다.
  • 따라서 상위 레이어가 바뀌면 전체 이미지 레이어 체인이 바뀐 것으로 간주되어
    동일한 명령어라도 캐시를 사용할 수 없다.

이미지 생성

4개의 이미지 레이어 생성, parent로 엮여져 있음

이미지 레이어 캐시 무효화

  • 2번 레이어는 캐시를 사용할 수 없게 되어 새로 생성된다.
  • 이때 3번과 4번도 이전과 동일한 명령어라고 하더라도 캐시를 사용할 수 없다.(Docker는 각 레이어가 부모(parent) 레이어를 기반으로 만들어지기 때문)
    • 즉, 3번의 부모(2번)가 바뀌었기 때문에, 3번도 새로 생성
    • 이어서 4번의 부모(3번)가 바뀌었기 때문에, 4번도 새로 생성

3-5. 적절한 빌드 캐시 사용

이미지 레이어 수정이 빈번한 명령어는 최대한 마지막에 쓴다.

Dockerfile-9

# Alpine 리눅스 이미지 
FROM alpine:3.15 
 
# entrypoint.sh 복사
COPY ./entrypoint.sh /
 
# Git 및 기타 도구를 설치
RUN apk fix 
RUN apk --update add git git-lfs less openssh \ 
	&& git lfs install \ 
    && rm -rf /var/lib/apt/lists/* \ 
    && rm /var/cache/apk/* 
 
# 실행 권한 부여후, 실행
RUN chmod +x ./entrypoint.sh 
ENTRYPOINT ["/entrypoint.sh"]

  • entrypoint.sh를 수정하면 그 아래 레이어들(4개)을 다시 빌드한다.

Dockerfile-10

# Alpine 리눅스 이미지 
FROM alpine:3.15 
 
# Git 및 기타 도구를 설치
RUN apk fix 
RUN apk --update add git git-lfs less openssh \ 
	&& git lfs install \ 
    && rm -rf /var/lib/apt/lists/* \ 
    && rm /var/cache/apk/* 
 
# entrypoint.sh 복사
COPY ./entrypoint.sh /
 
# 실행 권한 부여후, 실행
RUN chmod +x ./entrypoint.sh 
ENTRYPOINT ["/entrypoint.sh"]

  • entrypoint.sh를 수정하면 그 아래 모든 레이어들(2개)을 다시 빌드한다.

정리

Docker는 명령어 순서대로 레이어를 생성하고, 위 레이어(parent)가 바뀌면 아래는 모두 캐시 무효화된다.

따라서 COPY, RUN chmod, ENTRYPOINT자주 바뀌는 명령어는 하단에 위치시키는 것이 좋다.

패키지 설치, OS 환경 구성 등 무거운 작업은 상단에 두어 캐시를 최대한 활용한다.


출처