캐시 GitHub 작업에서 Docker 빌드: 가장 빠른 방법은 무엇입니까?🤔 한 가지 연구.

요약: 이 글에서 나는 6가지 다른 방법으로GitHub 작업에서 Docker 구축을 캐시하여 구축 과정을 가속화하고 결과를 비교했다.각 방법을 10번 시도한 결과 GitHub 패키지의 Docker 레지스트리를 GitHub 작업의 내장 캐시가 아닌 구축 캐시로 사용하면 최고의 성능 이득을 얻을 수 있었다.

⚠️ Warning: This article has not been updated since its publication in April 2020. The approaches outlined here are probably out-of-date. Here are more updated takes on this issue:


배경 및 동기💬


GitHub의 구축 작업을 기다리는 데 지쳤습니다.😖
Jenkins와 같은 자체 위탁 관리 운영 프로그램과 달리 대부분의 클라우드 위탁 관리 구축 운영 프로그램은 무상태이며 매번 실행할 때마다 우리에게 원시적인 환경을 제공한다.이전에 실행된 파일을 저장할 수 없습니다.지구화가 필요한 것은 모두 외부화되어야 한다.
GitHub Actions has a built-in cache은 이 일을 완성하는 것을 돕는다.그러나 많은 방법으로 캐시를 만들 수 있다(먼저 생각한 것은 docker savedocker load).성능이 향상되면 캐시 저장 및 로드에 따른 오버헤드를 초과할 수 있습니까?GitHub Action의 내장 캐시를 사용하는 방법 외에 다른 방법이 있습니까?이것이 바로 이 연구의 목적이다.

고려 방법💡


이 실험을 진행하기 위해서, 나는 먼저 구축된 Docker 이미지를 캐시하는 방법에 대한 생각을 떠올렸다.나는 모두 여덟 가지 방법을 시험해 보았다.
  • 캐시 없음🤷‍♂️
  • 이것은 기선이다.
  • 캐시 없음(BuildKit)🤷‍♀️
  • 이것은 또 다른 기선이지만 BuildKit이다.
  • docker save docker load actions/cache 사용 docker save📦
  • 그림을 만든 후, 우리는 actions/cache 을 사용하여 그림을 tarball로 내보내고, docker load 을 사용하여 캐시를 내보낼 수 있습니다.후속 실행 중, 우리는 --cache-from 을 사용하여 캐시된 tarball에서 그림을 가져올 수 있습니다.그리고 우리는 actions/cache 로고가 있는 이미지를 만들 수 있다.
    이 메서드는 BuildKit as it only supports external caches located on the registry과 호환되지 않습니다.
  • 캐시/var/lib/docker 및 /var/lib/docker🤯
  • 아마도 우리는 모든 가져오기와 내보내기 작업을 할 필요가 없을 것이다. 전체 actions/cache 디렉터리를 캐시하기만 하면 된다.
  • 로컬 레지스트리 사용🐳
  • 로컬 호스트에서 run a filesystem-backed Docker registry을 실행하여 구축된 이미지를 이 등록표에 전송하고 actions/cache 캐시를 사용할 수 있습니다.다음 실행 중, 우리는localhost 등록표에서 최신 이미지를 추출하고, --cache-from arg가 있는 추출 이미지를 사용할 수 있습니다.
  • 로컬 레지스트리 및 actions/cache(BuildKit) 사용🐋
  • 위와 동일하지만 BuildKit을 사용합니다.
    BuildKit를 사용하면 docker pull을 실행할 필요가 없습니다.BuildKit already expects the cached image to be located on a registry.은 제한적인 것으로 보이지만 성능 향상을 가져옵니다. 캐시 결과가 적용되지 않으면 BuildKit는 추출 이미지를 건너뜁니다.
  • GitHub 패키지의 Docker 레지스트리를 캐시로 사용🐙
  • GitHub은 이미 a package registry을 제공했기 때문에 우리는 자신의 파일 시스템이 지원하는 등록표를 실행할 필요가 없을 수도 있습니다!

  • GitHub 패키지의 Docker 레지스트리를 캐시로 사용(BuildKit)🦑
  • 위와 동일하지만 BuildKit을 사용합니다.

    실패한 방법💥


  • 접근🤯, 캐시를 생성할 때 많은 권한 오류가 발생했기 때문에 actions/cache이 있는 Cache/var/lib/docker가 실패했습니다.sudo chmod을 사용하더라도 적절한 캐시를 만들 수 있습니다.

  • 접근🦑, GitHub 패키지를 캐시 (BuildKit) 로 사용하는 데 실패했습니다. 이 문서를 작성할 때 GitHub 패키지 등록표에서 요청 캐시 목록을 지원하지 않기 때문입니다.캐시된 이미지를 재사용하려고 하면 다음 생성으로 인해 이 메시지가 발생합니다. ERROR: httpReaderSeeker: failed open: could not fetch content descriptor
  • 그래서 우리는 네 가지 방법이 남았다(📦, 🐳, 🐋, 🐙), 2개의 베이스라인 제외(🤷‍♂️ 및🤷‍♀️).

    이미지 설정🏛

    docker build을 실행하는 데 걸리는 시간을 줄일 수 있는 최적의 구축 환경🤩, 그러나 불행하게도 약간의 지출을 끌어들일 수 있다😞.
    오버헤드 시간은 다음과 같습니다.
  • 저장된 캐시 복구(근접)📦, 🐳, 🐋);
  • 캐시에서 불러오는 tarball에서 그림 가져오기 (방법📦);
  • 로컬 Docker 레지스트리 실행(근접)🐳, 🐋);
  • Docker 레지스트리에서 추출(거의🐳, 🐋, 🐙);
  • 생성된 그림을 tarball로 내보내기 (방법📦);
  • 레지스트리로 이미지 푸시(거의🐳, 🐋, 🐙);
  • 캐시 저장(근접)📦, 🐳, 🐋).
  • 내 경험에 의하면
  • 구축 시간의 증가는 주로 프로젝트의 복잡성, 즉 구축된 CPU 시간과 관련이 있다.
  • 의 지출 시간은 주로 캐시 내용의 크기에 따라 증가한다. 즉, 서열화와 전송 내용의 IO 시간이다.
  • 이 실험에서 우리는 충분한 이미지를 원한다. 이렇게 하면 우리의 측정에서 구축 시간과 비용이 모두 뚜렷해진다.
    이로 인해 Dockerfile에 약간 비대해진 이미지가 생성됩니다.🤪:
    FROM node:12
    RUN yarn create react-app my-react-app
    RUN cd my-react-app && yarn build
    RUN npm install -g @vue/cli && (yes | vue create my-vue-app --default)
    RUN cd my-vue-app && yarn build
    RUN mkdir -p my-tests && cd my-tests && yarn add playwright
    

    방법론🔬


    모든 방법을 실행하는 GitHub 작업 워크플로우를 만들었습니다.나는 20번 뛰었다.
  • 10회, Dockerfile을 변경할 때마다 캐시를 비활성화(actions/cache).캐시가 명중되지 않은 장면입니다.
  • 번, 매번 Dockerfile을 유지합니다.캐시 적중 장면입니다.
  • 이후 각 방법과 장면의 결과는 함께 평균된다.
    예외는 거의 없습니다.
  • 베이스라인에 캐시가 없습니다.따라서 모든 20개의 구축은 캐시 미명중으로 간주된다.
  • 진근🐙 외부 등록표를 사용하기 때문에 그림은 층층이 캐시되고 효력을 상실합니다.내가 이 실험 방식을 설정했기 때문에, 모든 20개의 구축은 최종적으로 캐시에 명중되었다.나는 너무 게으르기 때문에 10번의 구축을 더 이상 실행할 수 없다. 그래서 나는 캐시가 명중되지 않은 상황이 캐시가 없는 것과 첫 번째 이미지를 푸시하는 데 필요한 시간과 같다고 가정할 것이다.
  • 결실📊


    모든 구축을 실행한 후에, 나는 GitHub Actions API으로 모든 단계의 시간을 검색했다.나는 결과를 구글 표에 넣고 데이터 투시표를 운행하며 결과를 정리했다.

    🎖 결전



    녹색 막대는 장면에 대한 캐시 적중 시간을 나타냅니다.빨간색 막대는 캐시가 장면에 명중하지 않는 데 필요한 추가 시간을 표시합니다.

    🤷‍♂️ 베이스라인🤷‍♀️



    캐시 없이 BuildKit만 사용하면 성능이 향상됩니다.꼬박 1분을 절약했다.

    📦 아스팔트 볼



    캐시 크기는 846MB입니다.docker save의 속도가 매우 느리다는 사실이 증명되었다.따라서 이 tarball을 캐시에 업로드하는 데도 시간이 오래 걸린다.

    🐳 로컬 등록소



    캐시 크기는 855MB입니다.Docker 내부의localhost에서 docker push을 파일 시스템이 지원하는 등록표로 실행하는 속도가 docker save보다 빠르다는 사실이 증명되었다.docker pulldocker load도 마찬가지다.

    🐋 로컬 레지스트리 및 BuildKit



    캐시 크기는 855MB입니다.BuildKit 는 docker build 을 실행하면 로컬 레지스트리에서 이미지를 추출하므로 별도의 docker pull 단계가 없습니다.🐳.

    🐙 GitHub 패키지 레지스트리



    BuildKit 를 사용할 수는 없지만 외부 레지스트리를 사용하면 계층별로 캐시를 구축할 수 있습니다.내가 시도해 본 모든 방법 중에서 이런 방법의 효과가 가장 좋다.🏆
    그러나 저장소에서 게시된 패키지에 구축 캐시 패키지가 나열됩니다.😂

    실제 세계에 더욱 가까운 예


    잠재적인 이득을 시험하기 위해 나는 위에서 docker-compose build을 운행해 보았다.캐시가 없는 상황에서 웹 이미지를 구축하는 데 많은 시간이 걸린다.GitHub Package Registry를 캐시로 사용하면 이미지를 구축하는 데 걸리는 시간이 줄어듭니다.

    결론


    이 방법을 구현하는 코드를 찾을 수 있습니다.

    dtinth / github 조작 docker층 캐시poc



    구축 성능 개선에 대해 이야기할 때, 많은 글들이 있는데, 매 편마다 서로 다른 예를 사용하여 서로 다른 방법을 추천한다.모든 방법의 효과가 어떠한지 알기 어렵다.
    이 문제를 연구하는 과정에서 나는 또 다른 다른 방법을 시도하면 더 많은 새로운 방법을 발견할 수 있다는 것을 알아차렸다.예를 들면, 나는 이런 방법을 시도해 본 적이 없습니까🐳 (로컬 Docker 등록표) "오! GitHub 패키지 등록표는 하나야! 내가 그것을 사용해서 Action 캐시를 완전히 뛰어넘을 수 있을까? 한번 해보자!"그리고 해결 방법을 제시했다🐙.
    그래서 나는 Docker와 CI 작업 흐름을 구축하고 싶을 때 이것이 내가 존재하고 싶은 그런 문장이라고 말하고 싶다.나는 우리가 더 많은 방법과 도구를 위해 더 많은 노점을 할 수 있기를 바란다.
    읽어주셔서 감사합니다!

    좋은 웹페이지 즐겨찾기