Docker Image 는 매 Instruction 마다 layer로 구성되며 이 중간 과정을 Cache해 놓는다.
How the Build Cache works
도커 빌드 캐시를 이해하면 더 빠른 이미지를 생성하는 도커 파일을 작성할 수 있다.
아래 예시는 C 언어로 작성된 작은 도커 파일이다.
# syntax=docker/dockerfile:1
FROM ubuntu:latest
RUN apt-get update && apt-get install -y build-essentials
COPY main.c Makefile /src/
WORKDIR /src/
RUN make build
도커 파일에 있는 각 명령어는 최종 이미지의 레이어로 변환된다. 각 명령어가 변환되 이미지 레이어를 스택으로 생각할 수 있고, 각 레이어는 이전 레이어 위에 더 많은 콘텐츠를 추가한다.
레이어가 변경(명렁어 실행 결과물이 변경)될 때마다 해당 레이어를 다시 빌드해야한다.
예를 들어서 main.c 가 변경되었다고 가정하면, `COPY` 명령어가 재실행되어야 변경사항이 최종 이미지에 반영된다.
레이어가 변경되면 그 뒤에 오는 다른 레이어도 영향을 받는다. `COPY` 명령어가 있는 레이어가 재실행되면 그 뒤에 오는 레이어도 모두 다시 실행된다.
Docker 빌드 캐시의 요점
레이어가 변경되면 모든 다운스트림 레이어도 다시 빌드된다. 만인 `main.c` 레이어만 변경되고 그 뒤에 있는 레이어에는 변경사항이 없다할지라도 다시 빌드된다는 것이다.
캐시를 사용하여 효율적인 빌드 수행하는 방법
https://docs.docker.com/build/cache/invalidation/
1. 캐시 무효화
이미지 빌드 시 각 명령어에 대해 빌더가 빌드 캐시에 있는 명령어를 재사용할 수 있는지 확인한다.
캐시 무효화에는 3가지가 있다.
- 기본규칙 (General rules)
- Run instructions
- Build secrets
기본 규칙
빌드 캐시 무효화의 기본 규칙은 다음과 같다
- 빌더가 Base Image가 이미 캐시되어있는지 확인
- 확인 후 각 명령어는 캐시된 레이어와 비교 (캐시된 레이어가 명령어의 결과물과 정확히 일치하지 않으면 캐시가 무효화)
- 대부분 Dockerfile 명령어를 캐시된 레이어와 비교하는 것으로 충분하지만 일부 명령어는 추가 검사가 필요
- `ADD`, `COPY`,`RUN --mount-type=bind` 이 세 명령어 같은 경우, 빌더가 각각의 파일마다 파일 메타데이터 등의 Cache Checksum을 계산하여 캐시가 유효한지 여부를 판별한다. 파일이나 파일 메타 데이터가 변경된 경우 캐시는 무효화된다.
- 파일의 수정 시간(`mtime`)은 Cache Checksum을 계산할 때 고려되지 않음.
- `ADD`, `COPY` 명령어 이외에도 캐시 검사에서 컨테이너 안에 있는 파일은 비교해보지 않는다. (캐시 검사에서 제외)
- `RUN apt-get -y update` 명령어의 경우, 컨테이너로 업데이트된 파일은 캐시가 있는지 고려할 대상이 아니다. 이 경우 커맨드 문자열 자체만 비교한다.
캐시가 무효화 된 경우
Dockerfile 의 모든 하위 명령은 새로운 이미지를 생성하고 캐시 사용 X. (위에서 설명한 내용과 같은 내용)
빌드에 여러 계층이 포함되어 있고 빌드 캐시를 재사용하여 최적화 하기위해서는, 변경 빈도가 낮은 명령을 Dockerfile 위에서 정의하자.
2. Run Instructions
`RUN` 명령어에 대한 캐시는 빌드중 자동으로 무효화되지 않는다.
Dockerfile이 아래와 같다고 가정해보자
FROM alpine:3.20 AS install
RUN apk add curl
위 도커파일에서 `curl`의 버전이 항상 최신이라는 보장이 없다.
시간이 흘러 curl 의 새로운 버전이 출시되었다고 가정해보자, 이미지를 다시 빌드해도 캐시된 레이어를 사용하므로 처음에 빌드한 이미지에서 다운받은 패키지와 동일한 패키지를 다운받게 된다.
이때 RUN 명령어를 캐시를 사용하지 않고 다시 실행하려면 다음과 같이 수행하면 된다.
- 빌드 전에 빌드 캐시를 지운다.
docker builder prune
- `--no-cache` 또는 `--no-cache-filter` 옵션을 사용해서 캐시를 무효화할 특정 빌드 단계를 지정할 수 있다.
docker build --no-cache-filter install .
3. Build Secrets
Build Secrets는 빌드 캐시의 일부가 아니다. Secrets 값을 변경해도 캐시 무효화는 발생하지 않는다.
Secrets 값을 변경한 후 캐시 무효화를 강제로 실행하려면, 변경하려는 Secrets값을 빌드 인수로 전달하면 된다.
FROM alpine
ARG CACHEBUST
RUN --mount=type=secret,id=TOKEN,env=TOKEN \
some-command ...
TOKEN="tkn_pat123456" docker build --secret id=TOKEN --build-arg CACHEBUST=1 .
ID와 mount 경로 같은 경우 cache checksum에 참여하므로, 이 값이 변경되면 캐시가 무효화 된다.
'DevOps > Docker' 카테고리의 다른 글
[Gitub Action] Pull Requst 했을 때 프로젝트 빌드 테스트하기 (1) | 2024.10.29 |
---|---|
[Docker] Multi-Stage (0) | 2024.10.23 |
[Docker] Build Context (0) | 2024.10.23 |
[Docker] Dockerfile 살펴보기 (0) | 2024.10.19 |