Search

Github Action에서 Docker Image Layers 캐싱하기

최근 컨테이너 이미지 빌드를 위한 워크플로 툴을 Jenkins에서 Github Action으로 옮겼다. 그런데 Github Action runner가 매번 새로 뜨면서 이미지 레이어가 캐싱되지 않고 있었다. 개발자가 더 빨리 빌드되어야 한다고 했고, 이를 해결했던 방법과 그 기술의 배경을 정리한다.

검색

참으로 일반적인 요구사항. 남들도 겪었을 또 해결했을 문제이다. 검색한다. 키워드는 github action docker layer caching. 가장 먼저 나오는 블로그 글을 확인했다:
주욱 내려보면, 이미 쓰고 있는 docker/build-push-action 워크플로에 인자 cache-from: type=ghacache-to: type=gha,mode=max 를 추가한다. gha 가 github action을 위한 dedicated한 방법 같아 보이고, 백엔드로 github action API를 사용한다고 한다.
더 deep-dive 하고 싶지만… 일단 테스트 해본다.

수정

기존 composite 워크플로에 주석으로 설명한 다음을 추가한다(*전사의 공통 요구사항=컨테이너 이미지 빌드를 통일하기 위해 composite 워크플로를 만들고 배포했다):
name: Docker Image Build and Push description: "Build and push docker image to ECR specified account and repository" inputs: ... runs: using: "composite" steps: ... - name: Set up Docker Buildx # github action이 제공하는 buildx 인스턴스를 uses: docker/setup-buildx-action@v2 # 활용해야 gha 캐시가 가능하다 ... - name: Build and push uses: docker/build-push-action@v3 with: ... cache-from: type=gha # github action 안에서 캐시 cache-to: type=gha,mode=max
YAML
복사

결과

테스트를 위해 composite 워크플로를 호출하는 곳에서 on.workflow_dispatch 트리거를 추가하고 수동으로 두번 연속 실행해봤다.
성공이다. 빌드 시간은 25분 → 5분으로 80% 가량 줄었고, 오래 걸리던 instructions에서 캐시를 활용하는 걸 확인할 수 있다.
5분 중의 대부분 시간은 github action ubuntu runner의 디스크를 확보하는데 사용한다. 자세한 내용은 다음에 다른 포스트에서 정리할 것.
캐시를 활용한다 하더라도 이미지 크기나 빌드 시간이 너무 크다. 개발자와 함께 줄여야 할 것

Deep Dive

컨테이너 이미지의 캐시 레이어를 활용하는 원리나 모범사례는 이미 알고 있었다:
로컬에서 빌드할 땐 실험도 몇 번 했었다:
이번에 중요한건 이걸 github action에서 어떻게 활용하느냐이다.
먼저 위에서 추가한 docker/setup-buildx-action이 필요하다. 이 액션(composite 워크플로)은 github action에서 buildx를 사용할 수 있게 셋업한다. buildx는 BuildKit의 확장 빌드 기능을 위한 CLI이다. 결국엔 이 BuildKit에 외부 캐시, github action backend로 내보내는 기능이 있다:
setup-buildx-action → buildx → BuildKit; export cache to external such as Github Action
아직 실험 단계의 기능이다(experimental)
레포 당 10GB의 크기 제한이 있다. → 오래된 순서로(LRU?) evict 한다.
7일의 retention이 있다.
위 제약을 이해하고, 한도에 다다르면 관리가 필요할 수 있다. Actions 탭에서 캐시 엔트리를 관리할 수 있다(벌써 10GB 거의 다 썼네…)
BuildKit을 만드는 도커에서 제공하는 기능이고, 도커 쪽 문서도 있다:
mode를 제외한 다른 param은 github action workflow 내에선 자동으로 채워지는거 같다(아닌 곳에서 10GB 무료극한의 이득충? blob storage를 사용하기 위해 구현할 수 있을거 같다).
BuildKit의 external cache로써 github action blob 외에 지원 되는 다른 것들도 있다:
inline
registry

습득 교훈(주절주절)

시도를 먼저해보는 것이 유효한 경험이었다. 또 널리 쓰는 기술 스택에선 “이 정돈 있을거야”라는 자세도 유효했다.
우선 그걸 “사용”한 후에 이해하는 것은 workaround가 아니다. 사용하라고 제공되는 것이다. 어차피 관리를 위해서 그 후에 뒷 배경에 대한 이해는 필요하다.
위에서 언급한 “github action ubuntu runner의 디스크를 확보하는 방법”을 다음 글로 정리해야지(그리고 여기에 링크 달아야지).