GitLab CI/CD에서의 캐싱

Tier: Free, Premium, Ultimate Offering: GitLab.com, Self-managed, GitLab Dedicated

캐시는 작업이 다운로드하고 저장하는 하나 이상의 파일입니다. 동일한 캐시를 사용하는 후속 작업들은 파일을 다시 다운로드할 필요가 없기 때문에 더 빨리 실행됩니다.

.gitlab-ci.yml 파일에서 캐시를 정의하는 방법은 캐시 참조를 참조하세요.

캐시와 아티팩트의 차이점

인터넷에서 다운로드한 패키지와 같은 종속성에 대해 캐시를 사용합니다. 캐시는 GitLab Runner가 설치된 위치에 저장되며, 분산 캐시가 활성화되면 S3에 업로드됩니다.

아티팩트는 단계간에 중간 빌드 결과를 전달하는 데 사용합니다. 아티팩트는 작업에 의해 생성되어 GitLab에 저장되며 다운로드할 수 있습니다.

아티팩트와 캐시는 모두 프로젝트 디렉토리를 기준으로 경로를 정의하고, 해당 경로 외부의 파일에 연결할 수 없습니다.

캐시

  • cache 키워드를 사용하여 작업별로 캐시를 정의합니다. 그렇지 않으면 비활성화됩니다.
  • 후속 파이프라인에서 캐시를 사용할 수 있습니다.
  • 동일한 파이프라인의 후속 작업은 종속성이 동일하다면 캐시를 사용할 수 있습니다.
  • 다른 프로젝트는 캐시를 공유할 수 없습니다.
  • 기본적으로 보호 및 비보호 브랜치는 캐시를 공유하지 않습니다. 그러나 이 동작을 변경할 수 있습니다.

아티팩트

  • 작업별로 아티팩트를 정의합니다.
  • 동일 파이프라인의 후반 단계에서 후속 작업은 아티팩트를 사용할 수 있습니다.
  • 다른 프로젝트는 아티팩트를 공유할 수 없습니다.
  • 기본적으로 아티팩트는 30일 후에 만료됩니다. 사용자 정의 만료 시간을 정의할 수 있습니다.
  • 최신 아티팩트를 유지하는 기능이 활성화되어 있는 경우 최신 아티팩트는 만료되지 않습니다.
  • 어떤 작업이 아티팩트를 가져올지 제어하려면 의존성을 사용하세요.

좋은 캐싱 방법

캐시의 최대 가용성을 보장하기 위해 다음 중 하나 이상을 수행하세요:

캐시를 효율적으로 활용하기 위해 런너를 사용하는 방법:

  • 모든 작업에 동일한 런너를 사용합니다.
  • 캐시를 S3 버킷에 저장하는 분산 캐싱을 사용하는 여러 런너를 사용합니다. GitLab.com의 인스턴스 런너가 이렇게 작동합니다. 이러한 런너는 자동 스케일 모드에 있을 수 있지만 그럴 필요는 없습니다. 캐시 객체를 관리하기 위해 수명주기 규칙을 적용하여 일정 기간이 지난 후 캐시 객체를 삭제할 수 있습니다. 수명주기 규칙은 객체 저장 서버에서 사용할 수 있습니다.
  • 동일한 아키텍처를 가진 여러 런너를 사용하여 캐시를 저장하기 위해 공통 네트워크 마운트된 디렉터리를 공유합니다. 이 디렉터리는 NFS 또는 유사한 것을 사용해야 합니다. 이러한 런너들은 자동 스케일 모드여야 합니다.

여러 개의 캐시 사용

최대 4개의 캐시를 사용할 수 있습니다:

test-job:
  stage: build
  cache:
    - key:
        files:
          - Gemfile.lock
      paths:
        - vendor/ruby
    - key:
        files:
          - yarn.lock
      paths:
        - .yarn-cache/
  script:
    - bundle config set --local path 'vendor/ruby'
    - bundle install
    - yarn install --cache-folder .yarn-cache
    - echo 테스트 실행...

여러 캐시를 사용하고 대체 캐시 키와 결합하는 경우, 전역 대체 캐시가 검색되지 않는 각 캐시가 발견될 때마다 검색됩니다.

대체 캐시 키 사용

캐시 대체 키별

각 캐시 항목은 fallback_keys 키워드를 사용하여 최대 5개의 대체 키를 지원합니다. 작업이 캐시 키를 찾을 수 없는 경우 작업은 대신 대체 캐시를 가져오려고 시도합니다. 대체 키는 순서대로 검색되며 캐시가 발견될 때까지 검색됩니다. 캐시가 발견되지 않은 경우 새로운 캐시를 만들지 않고 해당 작업을 실행합니다. 예:

test-job:
  stage: build
  cache:
    - key: cache-$CI_COMMIT_REF_SLUG
      fallback_keys:
        - cache-$CI_DEFAULT_BRANCH
        - cache-default
      paths:
        - vendor/ruby
  script:
    - bundle config set --local path 'vendor/ruby'
    - bundle install
    - echo 테스트 실행...

이 예시에서:

  1. 작업은 cache-$CI_COMMIT_REF_SLUG 캐시를 찾습니다.
  2. cache-$CI_COMMIT_REF_SLUG를 찾을 수 없는 경우, 작업은 대체 옵션으로 cache-$CI_DEFAULT_BRANCH를 찾습니다.
  3. cache-$CI_DEFAULT_BRANCH 또한 찾을 수 없는 경우, 작업은 두 번째 대체 옵션으로 cache-default를 찾습니다.
  4. 발견된 캐시가 없는 경우, 작업은 새 캐시를 생성하지 않고 해당 작업이 완료되면 cache-$CI_COMMIT_REF_SLUG에 대한 새 캐시를 생성합니다.

대체 키는 cache:key와 동일한 처리 로직을 따릅니다:

전역 대체 키

$CI_COMMIT_REF_SLUG 사전 정의된 변수를 사용하여 cache:key를 지정할 수 있습니다. 예를 들어, 만약 $CI_COMMIT_REF_SLUGtest라면 test로 태그된 캐시를 다운로드하는 작업을 설정할 수 있습니다.

이 태그가 없는 캐시를 찾을 수 없다면, 존재하지 않을 때 사용할 캐시를 지정하기 위해 CACHE_FALLBACK_KEY를 사용할 수 있습니다.

다음 예시에서, 만약 $CI_COMMIT_REF_SLUG가 발견되지 않는다면, 작업은 CACHE_FALLBACK_KEY 변수로 정의된 키를 사용합니다:

variables:
  CACHE_FALLBACK_KEY: fallback-key

job1:
  script:
    - echo
  cache:
    key: "$CI_COMMIT_REF_SLUG"
    paths:
      - binaries/

캐시 추출 순서는 다음과 같습니다:

  1. cache:key의 검색 시도
  2. fallback_keys에 지정된 각 항목의 순서대로 검색 시도
  3. CACHE_FALLBACK_KEY의 전역 대체 키에 대한 추출 시도

캐시 추출 과정은 첫 번째 성공적인 캐시를 검색한 후 중지됩니다.

특정 작업용 캐시 비활성화

전역으로 캐시를 정의하면 각 작업이 동일한 정의를 사용합니다. 각 작업에 대해 이 동작을 무시하려면 빈 목록을 사용하세요:

job:
  cache: []

전역 구성 상속, 하지만 각 작업마다 특정 설정 재정의

앵커를 사용하여 전역 캐시를 덮어쓰지 않고 캐시 설정을 재정의할 수 있습니다. 예를 들어, 하나의 작업에서 policy를 재정의하려는 경우:

default:
  cache: &global_cache
    key: $CI_COMMIT_REF_SLUG
    paths:
      - node_modules/
      - public/
      - vendor/
    policy: pull-push

job:
  cache:
    # 모든 전역 캐시 설정 상속
    <<: *global_cache
    # policy 재정의
    policy: pull

자세한 정보는 cache: policy를 참조하세요.

캐시의 일반적인 사용 사례

보통 캐시는 작업을 실행할 때마다 종속성이나 라이브러리와 같은 콘텐츠를 다운로드하는 것을 피하기 위해 사용합니다. Node.js 패키지, PHP 패키지, Ruby 젬, Python 라이브러리 등이 캐시될 수 있습니다.

예시는 GitLab CI/CD 템플릿을 참조하세요.

동일 브랜치 내의 작업 간 캐시 공유

각 브랜치의 작업이 동일한 캐시를 사용하도록하려면 key: $CI_COMMIT_REF_SLUG로 캐시를 정의하세요:

cache:
  key: $CI_COMMIT_REF_SLUG

이 구성은 캐시 덮어쓰기를 실수로 방지합니다. 그러나 병합 요청의 첫 번째 파이프라인은 느릴 수 있습니다. 브랜치로 커밋이 푸시되면 캐시가 재사용되어 작업이 빨라집니다.

작업 및 브랜치별 캐싱을 활성화하려면:

cache:
  key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"

단계 및 브랜치별 캐싱을 활성화하려면:

cache:
  key: "$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG"

다른 브랜치의 작업 간 캐시 공유

모든 브랜치 및 모든 작업에 대해 동일한 키를 사용하여 캐시를 공유하려면:

cache:
  key: one-key-to-rule-them-all

브랜치 간에 캐시를 공유하되 각 작업에 대해 고유한 캐시를 갖도록하려면:

cache:
  key: $CI_JOB_NAME

작업의 캐시 정책을 제어하기 위해 변수 사용

기본 브랜치와의 변경 사항에 따라 당겨서 밀고 캐시를 사용하는 유일한 차이점이 있는 경우, CI/CD 변수를 사용할 수 있습니다.

예를 들어:

conditional-policy:
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      variables:
        POLICY: pull-push
    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
      variables:
        POLICY: pull
  stage: build
  cache:
    key: gems
    policy: $POLICY
    paths:
      - vendor/bundle
  script:
    - echo "이 작업은 브랜치에 따라 캐시를 당겨서 미는 작업입니다."
    - echo "의존성 다운로드 중..."

이 예시에서 작업의 캐시 정책은 다음과 같습니다:

  • 기본 브랜치에 대한 변경 사항의 경우 pull-push
  • 다른 브랜치에 대한 변경 사항의 경우 pull

락 파일에서 캐시 키 계산하기

cache:key:files를 사용하여 package-lock.json 또는 yarn.lock과 같은 락 파일에서 캐시 키를 계산하고 여러 작업에서 재사용할 수 있습니다.

default:
  cache:  # 락 파일을 사용하여 모듈 캐싱
    key:
      files:
        - package-lock.json
    paths:
      - .npm/

Yarn을 사용하는 경우, zipped node_modules tar볼을 캐싱하기 위해 yarn-offline-mirror을 사용할 수 있습니다. 더 적은 파일을 압축해야 하기 때문에 캐시가 더 빨리 생성됩니다.

job:
  script:
    - echo 'yarn-offline-mirror ".yarn-cache/"' >> .yarnrc
    - echo 'yarn-offline-mirror-pruning true' >> .yarnrc
    - yarn install --frozen-lockfile --no-progress
  cache:
    key:
      files:
        - yarn.lock
    paths:
      - .yarn-cache/

PHP 종속성 캐싱

프로젝트에서 Composer를 사용하여 PHP 종속성을 설치하는 경우, 아래 예제는 모든 작업이 상속할 수 있도록 기본 cache를 정의합니다. PHP 라이브러리 모듈은 vendor/에 설치되며 브랜치별로 캐시됩니다.

default:
  image: php:7.2
  cache:  # 작업 간에 라이브러리 캐싱
    key: $CI_COMMIT_REF_SLUG
    paths:
      - vendor/
  before_script:
    # Composer 설치 및 실행
    - curl --show-error --silent "https://getcomposer.org/installer" | php
    - php composer.phar install

test:
  script:
    - vendor/bin/phpunit --configuration phpunit.xml --coverage-text --colors=never

Python 종속성 캐싱

프로젝트에서 pip를 사용하여 Python 종속성을 설치하는 경우, 아래 예제는 모든 작업이 상속할 수 있도록 기본 cache를 정의합니다. pip의 캐시는 .cache/pip/에 정의되며 브랜치별로 캐시됩니다.

default:
  image: python:latest
  cache:                      # pip의 캐시는 파이썬 패키지를 저장하지 않습니다
    paths:                    # https://pip.pypa.io/en/stable/topics/caching/
      - .cache/pip
  before_script:
    - python -V               # 디버깅을 위해 파이썬 버전 출력
    - pip install virtualenv
    - virtualenv venv
    - source venv/bin/activate

variables:  # 로컬 항목만 캐시할 수 있기 때문에 pip의 캐시 디렉토리를 프로젝트 디렉토리 내에 정의합니다.
  PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"

test:
  script:
    - python setup.py test
    - pip install ruff
    - ruff --format=gitlab .

Ruby 종속성 캐싱

프로젝트에서 Bundler를 사용하여 gem 종속성을 설치하는 경우, 아래 예제는 모든 작업이 상속할 수 있도록 기본 cache를 정의합니다. Gems는 vendor/ruby/에 설치되며 브랜치별로 캐시됩니다.

default:
  image: ruby:2.6
  cache:                                            # 빌드 간에 젬 캐싱
    key: $CI_COMMIT_REF_SLUG
    paths:
      - vendor/ruby
  before_script:
    - ruby -v                                       # 디버깅을 위해 루비 버전 출력
    - bundle config set --local path 'vendor/ruby'  # 지정된 젬을 설치할 위치
    - bundle install -j $(nproc)                    # ./vendor/ruby에 종속성 설치

rspec:
  script:
    - rspec spec

서로 다른 젬이 필요한 작업이 있는 경우, 전역 cache 정의에서 prefix 키워드를 사용합니다. 이 구성은 각 작업에 대해 다른 캐시를 생성합니다.

예를 들어, 테스트 작업은 프로덕션 배포 작업과 같은 젬이 필요하지 않을 수 있습니다.

default:
  cache:
    key:
      files:
        - Gemfile.lock
      prefix: $CI_JOB_NAME
    paths:
      - vendor/ruby

test_job:
  stage: test
  before_script:
    - bundle config set --local path 'vendor/ruby'
    - bundle install --without production
  script:
    - bundle exec rspec

deploy_job:
  stage: production
  before_script:
    - bundle config set --local path 'vendor/ruby'   # 지정된 젬을 설치할 위치
    - bundle install --without test
  script:
    - bundle exec deploy

Go 종속성 캐싱

프로젝트에서 Go Modules를 사용하여 Go 종속성을 설치하는 경우, 다음 예제는 모든 작업에서 확장할 수 있는 go-cache 템플릿에서 cache를 정의합니다. Go 모듈은 ${GOPATH}/pkg/mod/에 설치되며 모든 go 프로젝트에 대해 캐시됩니다.

.go-cache:
  variables:
    GOPATH: $CI_PROJECT_DIR/.go
  before_script:
    - mkdir -p .go
  cache:
    paths:
      - .go/pkg/mod/

test:
  image: golang:1.13
  extends: .go-cache
  script:
    - go test ./... -v -short

캐시의 가용성

캐싱은 최적화이지만 항상 작동한다는 보장은 없습니다. 필요한 경우 각 작업에서 캐시된 파일을 다시 생성해야 할 수 있습니다.

.gitlab-ci.yml에서 캐시를 정의한 후, 캐시의 가용성은 다음에 따라 달라집니다:

  • 러너 실행자 유형.
  • 캐시를 작업 간에 전달하기 위해 다른 러너가 사용되는지 여부.

캐시가 저장되는 위치

작업에 정의된 모든 캐시는 단일 cache.zip 파일에 보관됩니다. 러너 구성은 파일이 저장되는 위치를 정의합니다. 기본적으로 캐시는 GitLab Runner가 설치된 컴퓨터에 저장됩니다. 위치는 실행자 유형에 따라 다릅니다.

러너 실행자 유형 캐시의 기본 경로
Shell 로컬, gitlab-runner 사용자의 홈 디렉토리 하위: /home/gitlab-runner/cache/<user>/<project>/<cache-key>/cache.zip
Docker 로컬, 도커 볼륨 하위: /var/lib/docker/volumes/<volume-id>/_data/<user>/<project>/<cache-key>/cache.zip
Docker Machine (오토스케일 러너) 도커 실행자와 동일합니다.

작업에서 캐시 및 아티팩트를 동일한 경로에 저장하는 경우 캐시가 아티팩트보다 먼저 복원되기 때문에 캐시가 덮어쓰일 수 있습니다.

캐시 키 이름

글로벌 대체 캐시 키를 제외한 모든 캐시 키에 접미사가 추가됩니다.

예를 들어 cache.key$CI_COMMIT_REF_SLUG로 설정되고, mainfeature 두 개의 브랜치가 있다고 가정하면 다음 표는 결과적인 캐시 키를 표시합니다:

브랜치 이름 캐시 키
main main-protected
feature feature-non_protected
모든 브랜치에 대해 동일한 캐시 사용

캐시 키 이름을 사용하고 싶지 않은 경우 모든 브랜치(보호된 및 비보호된)가 동일한 캐시를 사용할 수 있습니다.

캐시 키 이름을 사용한 캐시 분리는 보안 기능이며, 개발자 역할을 하는 모든 사용자가 신뢰할 수 있는 환경에서만 비활성화해야 합니다.

모든 브랜치에 대해 동일한 캐시를 사용하려면:

  1. 왼쪽 사이드바에서 검색 또는 이동을 선택하고 프로젝트를 찾습니다.
  2. 설정 > CI/CD를 선택합니다.
  3. 일반 파이프라인을 확장합니다.
  4. 보호된 브랜치에 대해 별도의 캐시 사용 확인란을 비웁니다.
  5. 변경 사항 저장을 선택합니다.

아카이빙 및 추출 작업 방식

다음 예제에서는 두 개의 연속적인 스테이지에 두 개의 작업이 표시됩니다:

stages:
  - build
  - test

default:
  cache:
    key: build-cache
    paths:
      - vendor/
  before_script:
    - echo "Hello"

job A:
  stage: build
  script:
    - mkdir vendor/
    - echo "build" > vendor/hello.txt
  after_script:
    - echo "World"

job B:
  stage: test
  script:
    - cat vendor/hello.txt

한 대의 기기에 하나의 러너가 설치된 경우 프로젝트의 모든 작업은 동일한 호스트에서 실행됩니다:

  1. 파이프라인 시작.
  2. job A 실행.
  3. 캐시가 추출됨(발견된 경우).
  4. before_script가 실행됨.
  5. script가 실행됨.
  6. after_script가 실행됨.
  7. cache 실행 및 vendor/ 디렉토리가 cache.zip로 압축됩니다. 해당 파일은 러너의 설정cache: key에 따라 저장됩니다.
  8. job B 실행.
  9. 캐시가 추출됨(발견된 경우).
  10. before_script가 실행됨.
  11. script가 실행됨.
  12. 파이프라인 완료.

단일 러너를 사용하면 job Bjob A와는 다른 러너에서 실행되지 않는 문제가 발생하지 않습니다. 이 설정은 스테이지 간에 캐시를 재사용할 수 있게 보장합니다. build 스테이지에서 test 스테이지로 실행이 동일한 러너/기계에서 이루어질 때에만 작동합니다. 그렇지 않으면 캐시를 사용할 수 없을 수 있습니다.

캐싱 과정 중에 고려해야 할 몇 가지 사항이 있습니다:

  • 다른 캐시 구성이 있는 다른 작업이 동일한 zip 파일에 캐시를 저장하는 경우 덮어씁니다. S3 기반 공유 캐시를 사용하는 경우 해당 파일은 캐시 키를 기반으로 S3에도 추가로 업로드됩니다. 따라서 다른 경로를 가진 두 작업이 동일한 캐시 키를 가지고 있더라도 캐시가 덮어쓰입니다.
  • cache.zip에서 캐시를 추출할 때 zip 파일의 모든 항목이 작업의 작업 디렉토리(일반적으로 다운로드된 리포지토리)에 추출되며, 러너는 job A의 아카이브가 job B의 아카이브를 덮어 쓰는지 여부는 고려하지 않습니다.

캐시가 다른 러너에 의해 사용될 때 유효하지 않은 경우가 많기 때문에 이 작동 방식이 있습니다(예를 들어, 캐시에 이진 파일이 포함된 경우와 같이 다른 아키텍처에서 실행되는 경우). 또한 서로 다른 단계가 서로 다른 기계에서 실행될 수 있기 때문에 이 설정은 안전한 기본값입니다.

캐시 지우기

런너는 기존 데이터를 재사용하여 작업의 실행 속도를 높이기 위해 캐시를 사용합니다. 이로 인해 때로는 일관성 없는 동작이 발생할 수 있습니다.

캐시의 새로운 복사본으로 시작하는 두 가지 방법이 있습니다.

cache:key 변경으로 캐시 지우기

.gitlab-ci.yml 파일에서 cache:key의 값을 변경합니다. 다음으로 파이프라인이 실행될 때, 캐시는 다른 위치에 저장됩니다.

수동으로 캐시 지우기

GitLab UI에서 캐시를 지울 수 있습니다:

  1. 왼쪽 사이드바에서 검색 또는 이동을 선택하고 프로젝트를 찾습니다.
  2. 빌드 > 파이프라인을 선택합니다.
  3. 오른쪽 상단에서 런너 캐시 지우기를 선택합니다.

다음 커밋에서 CI/CD 작업은 새 캐시를 사용합니다.

참고: 캐시를 수동으로 지울 때마다, 내부 캐시 이름이 업데이트됩니다. 이름은 cache-<index> 형식을 사용하며 인덱스가 1씩 증가합니다. 이전 캐시는 삭제되지 않습니다. 러너 저장소에서 이 파일을 수동으로 삭제할 수 있습니다.

문제 해결

캐시 불일치

캐시 불일치가 있는 경우, 다음 단계를 따라 문제를 해결합니다.

캐시 불일치의 이유 해결 방법
여러 개의 독립 러너(자동 확장 모드가 아닌)가 하나의 프로젝트에 연결되어 공유 캐시 없이 사용됩니다. 프로젝트에는 하나의 러너만 사용하거나 분산 캐시가 활성화된 여러 러너를 사용합니다.
자동 확장 모드에서 분산 캐시를 사용하지 않은 러너를 사용합니다. 자동 확장 러너를 구성하여 분산 캐시를 사용하도록 합니다.
러너가 설치된 컴퓨터의 디스크 공간이 부족하거나, 분산 캐시가 설정된 경우, 캐시가 저장된 S3 버킷에 충분한 공간이 없습니다. 새 캐시를 저장할 공간을 확보하기 위해 일부 공간을 지우도록 합니다. 이 작업은 자동으로 이루어지지 않습니다.
작업에 동일한 key를 사용하여 다른 경로를 캐시하는 경우입니다. 각 작업에 다른 캐시 키를 사용하여 캐시 아카이브를 다른 위치에 저장하고 잘못된 캐시를 덮어쓰지 않도록 합니다.
러너에서 러너에 대한 분산 캐싱을 활성화하지 않은 경우입니다. 설명 = 거짓로 설정하고 러너를 다시 활성화합니다.

캐시 불일치 예제 1

프로젝트에 할당된 러너가 하나인 경우, 기본적으로 캐시는 러너의 기계에 저장됩니다.

만약 두 작업이 동일한 캐시 키를 가지고 다른 경로를 가진다면, 캐시가 덮어쓰일 수 있습니다. 예를 들어:

stages:
  - build
  - test

작업 A:
  stage: build
  script: make build
  cache:
    key: same-key
    paths:
      - public/

작업 B:
  stage: test
  script: make test
  cache:
    key: same-key
    paths:
      - vendor/
  1. 작업 A가 실행됩니다.
  2. public/cache.zip로 캐시됩니다.
  3. 작업 B가 실행됩니다.
  4. 이전 캐시가 있다면, 압축이 풀립니다.
  5. vendor/cache.zip으로 캐시되어 이전 것을 덮어씁니다.
  6. 작업 A가 다음으로 실행될 때는 이전과 다른 작업 B의 캐시를 사용하기 때문에 효과가 없습니다.

이 문제를 해결하려면, 각 작업에 다른 key를 사용하십시오.

캐시 불일치 예제 2

이 예제에서는 프로젝트에 여러 개의 러너가 할당되어 분산 캐시가 활성화되어 있지 않은 경우입니다.

두 번째로 파이프라인이 실행될 때, 작업 A작업 B가 자신의 캐시를 재사용하길 바랍니다 (이 경우에는 다릅니다):

stages:
  - build
  - test

작업 A:
  stage: build
  script: 빌드
  cache:
    key: 키A
    paths:
      - vendor/

작업 B:
  stage: test
  script: 테스트
  cache:
    key: 키B
    paths:
      - vendor/

key가 다르더라도, 다른 러너에서 실행될 경우 각 단계마다 캐시된 파일이 “정리”될 수 있습니다.

로컬 캐시가 없는 동시 러너

도커 실행자를 사용하여 여러 동시에 실행되는 작업에 대한 로컬로 캐시된 파일이 예상대로 존재하지 않을 수 있습니다. 캐시 볼륨의 이름은 각 러너 인스턴스에 대해 고유하게 구성되므로, 한 러너 인스턴스에 의해 캐시된 파일은 다른 러너 인스턴스에 의해 캐시에서 찾을 수 없을 것입니다.

동시 러너 간에 캐시를 공유하려면 다음을 사용할 수 있습니다:

  • 러너의 config.toml[runners.docker] 섹션에서 호스트에서 /cache에 매핑되는 단일 마운트 지점을 구성하여 각 컨테이너에서 고유한 볼륨 이름을 만들지 않도록 합니다.
  • 분산 캐시를 사용합니다.