도커 레이어 캐시

uchan·2023년 4월 4일
0

배경

최근 GHA 를 통하여 CI CD 환경을 구성하였는데 빌드 시간을 단축시키기 위하여 캐시를 적용하려고 시도하였다. 패키지 설치 또는 빌드 등 캐시를 적용하여 시간을 단축시켜왔는데 그 중 도커 이미지 빌드 시간을 단축시켰던 경험을 글로 적어 되새김질하고자 한다.

사전 지식

  • ECR
  • S3
  • Dockerfile
  • GHA

도커 레이어 캐시부터 알아보자

Dockerfile 에는 사용할 베이스 이미지, 환경 변수, 명령어 등을 작성되어있다. 다음과 같이 말이다.

FROM 3.9.16-slim-buster

COPY Pipfile Pipfile.lock /app

WORKDIR /app

RUN pipenv install

COPY src /app/src

RUN python setup.py install

ENTRYPOINT ["python", "main.py"]

위 이미지를 토대로 컨테이너를 띄우면 3.9 버전의 파이썬이 설치되어 있고, 현재 디렉토리에 있는 파일이 모두 복사되어 있으며 파이썬 패키지도 모두 설치되어있다. 이는 각 명령어 별로 레이어가 생성되어 쌓아지고 최종적으로 컨테이너 레이어를 통해 만들어진 것으로 볼 수 있다. 아래는 참고한 사이트의 이미지이다. 이를 보면 쉽게 레이어가 어떻게 쌓이는지 이해가 될 것이다.

레이어 캐시

개발을 하다보니 소스코드를 수정하여 빌드할 때 변경사항이 생기고, 패키지 인스톨 과정은 대부분 동일하다. 즉, 위 Dockerfile 에서 Pipfile 을 통해 패키지 설치하는 과정까지는 웬만하면 바뀌지 않는다는 것이다. 따라서 해당 레이어까지는 캐시를 적용하고 그 다음부터는 캐시를 적용하지 않는다면 빌드시간이 매우 단축될 것이다. 이는 이미 도커에 기본값으로 설정되어 있어 자동으로 레이어 캐시가 적용된다.

GHA 에서 레이어 캐시...

깃헙 액션에서는 크게 두 가지의 러너가 존재한다.

  • self-hosted runner
  • github 에서 제공하는 runner

보통 레이어 캐시를 저장하는 곳은 로컬이다. 그러나 깃헙에서 제공하는 러너를 사용한다면 이전에 빌드한 러너와 이후 빌드할 러너는 다를테니 당연히 캐시가 적용이 안된다. 반면 self-hosted runner 에서 빌드한다면 이전에 빌드한 러너를 그대로 사용할 수 있으니 레이어 캐시가 적용된다.
(만약 scalable self-hosted runner 를 적용하였다면 러너가 바뀔 수도 있으니 레이어 캐시는 적용이 안 될 것이다)

그럼 GHA 에서는 어떻게 레이어 캐시를 적용할 수 있을까?

GHA 에서 제공하는 캐시를 사용
actions/cache@v3 액션을 통해 깃헙액션에 캐시로 저장할 수 있다. 실제로 대부분 깃헙 액션에서 캐시를 해야될 때 actions/cache 액션을 다수 사용한다. 그러나 이는 10GB 까지 저장할 수 있다(이후 정책이 바뀔 수도 있음).

CLOUD PLATFORM 에 원격저장소를 사용
나의 경우 AWS 를 주로 이용하니 S3 를 사용하여 캐시를 하였다. 주로 buildx 를 통해 멀티 플랫폼으로 이미지를 빌드할텐데 이때 cache-from, cache-to 를 통해 캐시 저장소를 지정할 수 있다.

  • CLI
# ref: github.com/moby/buildkit

buildctl build ... \
  --output type=image,name=docker.io/username/image,push=true \
  --export-cache type=s3,region=eu-west-1,bucket=my_bucket,name=my_image \
  --import-cache type=s3,region=eu-west-1,bucket=my_bucket,name=my_image
  • GHA workflow YAML
# 깃헙액션에서 build-push-action 을 사용한다면
 - name: Build and push
   uses: docker/build-push-action@v4
   with:
     context: .
     push: true
     tags: user/app:latest
     cache-from: type=s3,region=eu-west-1,bucket=my_bucket,name=my_image
     cache-to: type=s3,region=eu-west-1,bucket=my_bucket,name=my_image

참고로 위 cache-from, cache-totype=gha 로 넣어주면 GHA 캐시를 사용한다.

캐시는 되도록 작은 사이즈 파일을 지정하자
원격 저장소를 통해 캐시를 할 때 이미지 사이즈가 크다면 파일을 내려받고 업로드하는데 오래걸린다(이를 docker 에서는 import/export 라고 한다). 또한 캐시를 export 할 때 Docker 에서는 gzip 등 방식으로 압축하는데 이때 이미지가 크다면 preparing cache 단계에서도 당연히 오래걸린다. 따라서 캐시를 적용하기에 앞서 최대한 이미지의 사이즈를 줄이고 캐싱을 하는 것을 추천한다.

Reference

GitHub Actions에서 도커 캐시를 적용해 이미지 빌드하기

https://github.com/aws/containers-roadmap/issues/876

https://velog.io/@qf9ar8nv/Docker-Cache를-통해-build-최적화-하기

0개의 댓글