본문 바로가기
Q&A해결2026년 8월 14일1분 읽기

GitHub Actions에서 도커 빌드가 매번 캐시를 못 써서 5분씩 걸립니다

c
cicd_bomi
조회 768댓글 4

CI에서 도커 이미지 빌드하는 워크플로우인데, 코드 한 줄만 바꿔도 npm install부터 전부 다시 돕니다. 로컬에선 레이어 캐시 덕에 몇 초면 끝나는데 CI에선 매번 풀빌드라 5분 넘게 걸려요.

워크플로우는 대충 이렇습니다.

- uses: actions/checkout@v4
- run: docker build -t myapp:${{ github.sha }} .

러너가 매번 새로 떠서 캐시가 없는 건 알겠는데, 그럼 CI에서 도커 레이어 캐시는 어떻게 재사용하나요? 매번 5분은 좀 아깝네요.

댓글 4

김김영삼2개월 전
러너가 job마다 새로 떠서 이전 빌드의 로컬 레이어 캐시가 통째로 사라지는 게 원인이에요. 그래서 plain docker build로는 CI에서 캐시가 절대 재사용이 안 돼요. buildx를 써서 캐시를 외부(깃허브 액션 캐시나 레지스트리)에 저장했다 불러와야 합니다.

docker/build-push-action 쓰는 게 제일 편해요.

- uses: docker/setup-buildx-action@v3
- uses: docker/build-push-action@v6
with:
context: .
push: false
tags: myapp:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max

cache-from/to type=gha가 깃허브 액션 캐시 백엔드에 레이어를 저장해서 다음 실행 때 끌어다 씁니다. 이러면 소스만 바뀌었을 때 npm install 레이어는 캐시에서 그대로 재사용돼요.

단, 이게 먹으려면 Dockerfile 레이어 순서가 받쳐줘야 해요. package*.json 먼저 COPY하고 npm ci 한 다음에 소스 전체를 COPY 하는 순서여야, 소스만 바뀌었을 때 의존성 레이어가 캐시 히트합니다. COPY . . 먼저 하고 npm install 하면 파일 하나만 바뀌어도 그 아래가 전부 무효화돼서 캐시 넣어도 소용없어요.
ccicd_bomi(guest)2개월 전
오 이걸로 확 줄었어요. 근데 mode=max로 하니 캐시가 계속 쌓이는 것 같은데, 깃허브 액션 캐시 용량 제한 있지 않나요? 모노레포라 이미지가 여러 개인데 서로 캐시를 덮어쓰진 않을까 걱정도 되고요.
김김영삼2개월 전
맞아요, 깃허브 액션 캐시는 리포당 총 10GB 제한이 있고, 넘으면 오래된 것부터 자동으로 밀려나요(LRU eviction). mode=max는 최종 이미지 레이어뿐 아니라 중간 빌드 스테이지 캐시까지 다 저장해서 히트율은 높은데 그만큼 용량을 많이 먹어요. 캐시가 자꾸 밀려서 히트율 떨어지면 mode=min으로 낮추는 것도 방법입니다.

모노레포에서 이미지 여러 개면 scope로 분리하세요.

cache-from: type=gha,scope=api
cache-to: type=gha,mode=max,scope=api

이미지마다 scope를 다르게(api, web, worker 식으로) 주면 서로 캐시를 안 덮어써요. scope 안 주면 다 같은 키를 공유해서 번갈아 무효화되는 참사가 납니다. 이미지 수가 많고 용량 압박이 심하면 아예 캐시를 레지스트리(type=registry, ECR이나 GHCR)로 빼는 게 10GB 제한을 안 받아서 더 안정적이에요. 규모 커지면 그쪽으로 가세요.
ccicd_bomi(guest)2개월 전
scope 나누니까 이미지별로 캐시 잘 물립니다. 5분짜리가 1분 안쪽으로 줄었어요. 말씀대로 하니 되네요 감사합니다 🙏
Ctrl+Enter로 등록