Docker에 대해 이것저것 알아보다가 Docker Cache란 것을 어느정도 공부하게 되었습니다. 평소에 신경쓰지 않았지만, 같은 docker image를 빌드하면 Docker에서 Cache를 사용하기 때문에 빠르게 빌드 되는 것을 확인할 수 있었습니다.
그러다 현재 CI/CD를 구현한 Github Action에서도 적용되는 줄 알고 있었던 Docker Cache가 적용되지 않는 것을 보고 어떻게 적용할 수 있는 방법이 없는지 찾아보다가 해결책을 찾았습니다.
Docker Cache를 이해하기 전에 먼저 Docker의 Layer에 대해 먼저 알아야 합니다.
Docker는 image를 통해 애플리케이션을 실행하는데, 이 때 내부적으로 image에서 Layer를 쌓으면서 실행됩니다. 즉, container를 실행하면, image를 통해 base layer가 쌓이고 그 위에서 container layer로 실행되는 것입니다.
ex)
그럼 Docker는 매번 이 Layer를 다 실행하면 속도가 매우 느릴 수 있습니다. 이를 위해 Docker는 Docker Cache를 통해 문제를 해결하였습니다. Layer에서 변한 것이 없다면 기존의 Layer를 재사용해서 build 과정에서 속도를 높이고, 중복된 Layer를 방지하여 저장공간의 효율까지 최소화 할 수 있습니다.
그럼 Docker에서 캐시가 되는 기준은 무엇일까요? Docker에서는 "ADD, COPY"를 제외하면 String의 형태만 확인하고, "ADD, COPY"는 String + 내용의 변화까지 확인해서 Cache의 적용 기준을 정합니다.
예를 들면, 위의 예시에서 FROM, ARG같은 경우는 명령어의 형태만 변하지 않으면 Docker cache를 적용하지만, COPY같은 경우 {JAR_FILE}의 내용이 바뀌었으면 같은 명령어라도 cache를 적용할 수 없습니다.
Docker에서는 이러한 방법을 통해 Docker build 과정을 최적화 하고, 빠른 build 과정을 수행 할 수 있습니다.
위의 과정대로 Docker build 과정을 cache를 통하면 빠르게 수행할 수 있습니다. 그러나 Github Action에서는 매번 Runtime 환경이 초기화 되기 때문에 Docker cache를 사용할 수 없다고 합니다.
실제로 Docker image에 영향을 주지 않는 commit을 통해 확인해 본 결과 build 속도가 이전과 같은 시간이 걸린 것을 확인할 수 있었습니다.
평균 build 시간: 약 41초
단순히 README.md 파일과 CI/CD용 yml 파일을 업데이트 했지만 Docker build는 비슷하게 걸린 것을 확인할 수 있습니다.
이를 해결하기 위해 방법을 찾아보던 중, 이미 Docker 공식 Github에서는 Github Action을 위한 Cache 방법을 만들었었습니다.
여기서 Registry와 Github 방법 2가지가 있습니다. Registry 방법에 대해 찾아봤더니 Docker hub와 같은 image 저장소에 image뿐만 아니라 Cache에 대한 값도 같이 저장되고, 이 값을 다시 가져와서 Docker cache를 적용한다고 합니다. 정확하지는 않지만, docker cache가 checksum을 통해 파일의 값을 확인하는데, 이 값을 같이 저장하고 사용한다는 것 같습니다.
저는 Github API를 통해 Blob방법을 채택했고, 이는 Backend 서버를 호출하여 Github SHA값을 통해 cache를 확인하고, binary를 통해 cache 값을 받습니다. 더 자세한 부분은 공식 Github를 참고하면 좋을 것 같습니다.
위의 방법을 통해 Github Action에도 Cache를 적용한 다음 확인한 결과 대략 반 정도로 시간이 줄어든 것을 확인할 수 있습니다.
수정 후 평균 build 시간: 25초
프로젝트 규모가 크지 않아서 별로 차이는 나지 않는 것처럼 보이지만, docker를 이용해서 큰 규모의 프로젝트를 진행하고 docker cache를 적극 이용한다면 더 좋은 결과를 얻을 수 있을 것 같습니다.
이상으로 Github Action에서 Docker cache를 적용하고 build 최적화를 진행해봤습니다. 읽어주셔서 감사합니다.
+ 추가 할 내용이나 부족한 부분이 있다면, 댓글 작성 부탁드립니다! :)