パイプライン キャッシュ

Azure DevOps Services

パイプライン キャッシュを使用すると、1 回の実行の出力またはダウンロードした依存関係を後の実行で再利用できるため、ビルド時間を短縮できます。これにより、同じファイルを再作成または再ダウンロードするコストを削減または回避できます。 キャッシュは、各実行の開始時に同じ依存関係が何度もダウンロードされるシナリオで特に便利です。 これは、多くの場合、数百または数千のネットワーク呼び出しを含む時間のかかるプロセスです。

キャッシュは、キャッシュを復元して保存する時間が、出力を最初から再度生成する時間よりも短い場合に、ビルド時間の向上に効果的です。 このため、キャッシュはすべてのシナリオで有効ではない可能性があり、実際にはビルド時間に悪影響を及ぼす可能性があります。

キャッシュは現在、CI ジョブとデプロイ ジョブではサポートされていますが、クラシック リリース ジョブではサポートされていません。

アーティファクトとキャッシュを使用する場合

パイプライン キャッシュと パイプライン成果物は 同様の関数を実行しますが、さまざまなシナリオ向けに設計されており、同じ意味で使用しないでください。

  • あるジョブで生成された特定のファイルを取得し、他のジョブと共有する必要がある場合は、パイプライン成果物を使用します (これらの他のジョブは失敗する可能性があります)。

  • 以前の実行のファイルを再利用してビルド時間を短縮する場合は、パイプライン キャッシュを使用します (これらのファイルを使用しない場合は、ジョブの実行機能に影響しません)。

Note

パイプライン キャッシュとパイプライン成果物は、すべてのレベル (無料および有料) で無料です。 詳細については、「 Artifacts storage consumption 」を参照してください。

キャッシュ タスク: そのしくみ

キャッシュは、 キャッシュ タスクを使用してパイプラインに追加されます。 このタスクは他のタスクと同様に機能し、ジョブの セクションに steps 追加されます。

実行中にキャッシュ ステップが検出されると、タスクは指定された入力に基づいてキャッシュを復元します。 キャッシュが見つからない場合は、ステップが完了し、ジョブの次のステップが実行されます。

ジョブ内のすべてのステップが実行され、ジョブの状態が成功したと仮定すると、スキップされなかった "キャッシュの復元" ステップごとに、特別な "ジョブ後: キャッシュ" ステップが自動的に追加され、トリガーされます。 この手順では、 キャッシュを保存します

Note

キャッシュは不変です。つまり、キャッシュが作成されると、その内容を変更することはできません。

キャッシュ タスクを構成する

キャッシュ タスクには、キーパスの 2 つの必須引数があります。

  • path: キャッシュするフォルダーのパス。 絶対パスまたは相対パスを指定できます。 相対パスは に対して $(System.DefaultWorkingDirectory)解決されます。

Note

定義済みの変数を使用して、キャッシュするフォルダーへのパスを格納できますが、ワイルドカードはサポートされていません。

  • key: 復元または保存するキャッシュの識別子に設定する必要があります。 キーは、文字列値、ファイル パス、またはファイル パターンの組み合わせで構成され、各セグメントは文字で | 区切られます。
  • 文字列:
    固定値 (キャッシュの名前やツール名など) または環境変数から取得された値 (現在の OS や現在のジョブ名など)

  • ファイル パス:
    コンテンツがハッシュされる特定のファイルへのパス。 このファイルは、タスクの実行時に存在する必要があります。 "ファイル パスのように見える " キー セグメント は、ファイル パスのように扱われることに注意してください。 特に、これには を含むセグメントが .含まれます。 これにより、この "ファイル" が存在しない場合にタスクが失敗する可能性があります。

    ヒント

    パスに似た文字列セグメントがファイル パスのように扱われないようにするには、次のように二重引用符で囲みます。 "my.key" | $(Agent.OS) | key.file

  • ファイル パターン:
    少なくとも 1 つのファイルと一致する必要がある glob スタイルのワイルドカード パターンのコンマ区切りのリスト。 例:

    • **/yarn.lock: ソース ディレクトリのすべての yarn.lock ファイル
    • */asset.json, !bin/**: bin ディレクトリの下を除く、sources ディレクトリの下のディレクトリにあるすべての asset.json ファイル

ファイル パスまたはファイル パターンによって識別されるファイルの内容は、動的キャッシュ キーを生成するためにハッシュされます。 これは、キャッシュされている内容を一意に識別するファイルがプロジェクトにある場合に便利です。 たとえば、、 Pipfile.lock などのpackage-lock.jsonyarn.lockGemfile.lockファイルはすべて一意の依存関係のセットを表しているため、キャッシュ キーで一般的に参照されます。

相対ファイル パスまたはファイル パターンは、 に対して $(System.DefaultWorkingDirectory)解決されます。

:

Yarn によってインストールされた依存関係をキャッシュする方法を示す例を次に示します。

variables:
  YARN_CACHE_FOLDER: $(Pipeline.Workspace)/.yarn

steps:
- task: Cache@2
  inputs:
    key: '"yarn" | "$(Agent.OS)" | yarn.lock'
    restoreKeys: |
       "yarn" | "$(Agent.OS)"
       "yarn"
    path: $(YARN_CACHE_FOLDER)
  displayName: Cache Yarn packages

- script: yarn --frozen-lockfile

この例では、キャッシュ キーには、静的文字列 ("yarn")、このキャッシュがオペレーティング システムごとに一意であるため、ジョブが実行されている OS、およびキャッシュ内の依存関係のセットを一意に識別するファイルの yarn.lock ハッシュの 3 つの部分が含まれています。

タスクが追加された後の最初の実行では、このキーで識別されたキャッシュが存在しないため、キャッシュ ステップで "キャッシュ ミス" が報告されます。 最後の手順の後に、 内 $(Pipeline.Workspace)/.yarn のファイルからキャッシュが作成され、アップロードされます。 次の実行では、キャッシュ ステップで "キャッシュ ヒット" が報告され、キャッシュの内容がダウンロードされて復元されます。

Note

Pipeline.Workspace は、すべてのディレクトリが作成されるパイプラインを実行しているエージェントのローカル パスです。 この変数の値は と Agent.BuildDirectory同じです。

キーの復元

restoreKeys は、複数の正確なキーまたはキー プレフィックスに対してクエリを実行する場合に使用できます。 これは、 がヒットしない場合 key に別のキーにフォールバックするために使用されます。 復元キーはプレフィックスでキーを検索し、結果として作成された最新のキャッシュ エントリを生成します。 これは、パイプラインが完全に一致するものを見つけられないが、代わりに部分キャッシュ ヒットを使用する場合に便利です。 複数の復元キーを挿入するには、復元キーを示す新しい行を使用して区切るだけです (詳細については、例を参照してください)。 復元キーが試行される順序は上から下になります。

セルフホステッド エージェントで必要なソフトウェア

アーカイブ ソフトウェア/プラットフォーム Windows Linux Mac
GNU Tar 必須 必須 いいえ
BSD Tar いいえ いいえ 必須
7-Zip 推奨 いいえ いいえ

上記の実行可能ファイルは、PATH 環境変数に一覧表示されているフォルダーに存在する必要があります。 ホストされるエージェントには含まれているソフトウェアが付属しています。これはセルフホステッド エージェントにのみ適用されます。

:

Yarn で復元キーを使用する方法の例を次に示します。

variables:
  YARN_CACHE_FOLDER: $(Pipeline.Workspace)/.yarn

steps:
- task: Cache@2
  inputs:
    key: '"yarn" | "$(Agent.OS)" | yarn.lock'
    restoreKeys: |
       yarn | "$(Agent.OS)"
       yarn
    path: $(YARN_CACHE_FOLDER)
  displayName: Cache Yarn packages

- script: yarn --frozen-lockfile

この例では、キャッシュ タスクはキーがキャッシュ内に存在するかどうかを確認しようとします。 キーがキャッシュに存在しない場合は、最初の復元キー yarn | $(Agent.OS)を使用しようとします。 これにより、そのキーと完全に一致するか、プレフィックスとしてそのキーを持つすべてのキーの検索が試行されます。 プレフィックス ヒットは、別 yarn.lock のハッシュ セグメントがあった場合に発生する可能性があります。 たとえば、次のキー yarn | $(Agent.OS) | old-yarn.lock がキャッシュ内に存在し、古い yarn.lock キーが とは異なるハッシュ yarn.lockを生成した場合、復元キーは部分的なヒットを生成します。 最初の復元キーが見つからない場合は、次の復元キー yarn が使用され、 で yarn始まるキーが検索されます。 プレフィックス ヒットの場合、最後に作成されたキャッシュ キーが結果として生成されます。

Note

パイプラインには、1 つ以上のキャッシュ タスクを含めることができます。 キャッシュ ストレージ容量に制限はなく、同じパイプラインのジョブとタスクが同じキャッシュにアクセスして共有できます。

キャッシュの分離とセキュリティ

異なるパイプラインと異なるブランチからのキャッシュ間の分離を確保するために、すべてのキャッシュはスコープと呼ばれる論理コンテナーに属します。 スコープは、あるパイプラインのジョブが別のパイプラインからキャッシュにアクセスできないことを保証するセキュリティ境界を提供し、PR を構築するジョブは PR のターゲット ブランチ (同じパイプラインの場合) のキャッシュへの読み取りアクセス権を持ちますが、ターゲット ブランチのスコープにキャッシュを書き込む (作成する) ことはできません。

実行中にキャッシュ ステップが検出されると、キーによって識別されるキャッシュがサーバーから要求されます。 次に、サーバーはジョブに表示されるスコープからこのキーを持つキャッシュを検索し、キャッシュ (使用可能な場合) を返します。 キャッシュの保存時 (ジョブの最後) には、パイプラインとブランチを表すスコープにキャッシュが書き込まれます。 詳細については、以下を参照してください。

CI、手動、スケジュールされた実行

Scope Read Write
ソース ブランチ はい はい
main ブランチ (既定のブランチ) はい いいえ

Pull request の実行

Scope Read Write
ソース ブランチ はい いいえ
ターゲット ブランチ はい いいえ
中間分岐 (など refs/pull/1/merge) はい はい
main ブランチ (既定のブランチ) はい いいえ

Pull request fork の実行

[Branch]\(ブランチ) Read Write
ターゲット ブランチ はい いいえ
中間分岐 (など refs/pull/1/merge) はい はい
main ブランチ (既定のブランチ) はい いいえ

ヒント

キャッシュのスコープは既にプロジェクト、パイプライン、ブランチであるため、プロジェクト、パイプライン、またはブランチの識別子をキャッシュ キーに含める必要はありません。

-キャッシュ復元の条件付け

一部のシナリオでは、キャッシュが正常に復元されると、異なる一連の手順が実行されます。 たとえば、キャッシュが復元された場合、依存関係をインストールするステップはスキップできます。 これは、タスク入力を cacheHitVar 使用して可能です。 この入力を環境変数の名前に設定すると、inexact復元キーのキャッシュヒット時にtrueキャッシュヒットが発生したときに変数が に設定されます。それ以外の場合は にfalse設定されます。 この変数は、 ステップ条件 またはスクリプト内から参照できます。

次の例では、キャッシュの install-deps.sh 復元時にステップがスキップされます。

steps:
- task: Cache@2
  inputs:
    key: mykey | mylockfile
    restoreKeys: mykey
    path: $(Pipeline.Workspace)/mycache
    cacheHitVar: CACHE_RESTORED

- script: install-deps.sh
  condition: ne(variables.CACHE_RESTORED, 'true')

- script: build.sh

Bundler

Bundler を使用する Ruby プロジェクトの場合は、Bundler で使用される環境変数をオーバーライド BUNDLE_PATH して、 Bundler が Gem を検索するパスを設定します。

:

variables:
  BUNDLE_PATH: $(Pipeline.Workspace)/.bundle

steps:
- task: Cache@2
  displayName: Bundler caching
  inputs:
    key: 'gems | "$(Agent.OS)" | Gemfile.lock'
    restoreKeys: | 
      gems | "$(Agent.OS)"
      gems
    path: $(BUNDLE_PATH)

Ccache (C/C++)

Ccache は、C/C++ 用のコンパイラ キャッシュです。 パイプラインで Ccache を使用するには、 がインストールされ、必要に応じて に追加されていることを確認Ccacheします (Ccache の実行モードに関するPATHページを参照してください)。 環境変数を CCACHE_DIR のパス $(Pipeline.Workspace) に設定し、このディレクトリをキャッシュします。

:

variables:
  CCACHE_DIR: $(Pipeline.Workspace)/ccache

steps:
- bash: |
    sudo apt-get install ccache -y    
    echo "##vso[task.prependpath]/usr/lib/ccache"
  displayName: Install ccache and update PATH to use linked versions of gcc, cc, etc

- task: Cache@2
  inputs:
    key: 'ccache | "$(Agent.OS)"'
    path: $(CCACHE_DIR)
    restoreKeys: | 
      ccache | "$(Agent.OS)"
  displayName: ccache

詳細については、「 Ccache 構成設定 」を参照してください。

Docker イメージ

Docker イメージをキャッシュすると、パイプラインの実行にかかる時間が大幅に短縮されます。

variables:
  repository: 'myDockerImage'
  dockerfilePath: '$(Build.SourcesDirectory)/app/Dockerfile'
  tag: '$(Build.BuildId)'

pool:
  vmImage: 'ubuntu-latest'
steps:
  - task: Cache@2
    displayName: Cache task
    inputs:
      key: 'docker | "$(Agent.OS)" | cache'
      path: $(Pipeline.Workspace)/docker
      cacheHitVar: CACHE_RESTORED                #Variable to set to 'true' when the cache is restored
    
  - script: |
      docker load -i $(Pipeline.Workspace)/docker/cache.tar
    displayName: Docker restore
    condition: and(not(canceled()), eq(variables.CACHE_RESTORED, 'true'))

  - task: Docker@2
    displayName: 'Build Docker'
    inputs:
      command: 'build'
      repository: '$(repository)'
      dockerfile: '$(dockerfilePath)'
      tags: |
        '$(tag)'

  - script: |
      mkdir -p $(Pipeline.Workspace)/docker
      docker save -o $(Pipeline.Workspace)/docker/cache.tar $(repository):$(tag)
    displayName: Docker save
    condition: and(not(canceled()), not(failed()), ne(variables.CACHE_RESTORED, 'true'))
  • key: (必須) - キャッシュの一意識別子。
  • path: (必須) - キャッシュするフォルダーまたはファイルのパス。

Golang

Golang プロジェクトの場合は、 go.mod ファイルにダウンロードするパッケージを指定できます。 GOCACHE変数がまだ設定されていない場合は、キャッシュをダウンロードする場所に設定します。

:

variables:
  GO_CACHE_DIR: $(Pipeline.Workspace)/.cache/go-build/

steps:
- task: Cache@2
  inputs:
    key: 'go | "$(Agent.OS)" | go.mod'
    restoreKeys: | 
      go | "$(Agent.OS)"
    path: $(GO_CACHE_DIR)
  displayName: Cache GO packages

Gradle

Gradle の 組み込みキャッシュ サポートを 使用すると、ビルド時間に大きな影響を与える可能性があります。 ビルド キャッシュを有効にするには、 の下の GRADLE_USER_HOME パス $(Pipeline.Workspace) に環境変数を設定し、 でビルド --build-cache を実行するか、ファイルに を追加 org.gradle.caching=true します gradle.properties

:

variables:
  GRADLE_USER_HOME: $(Pipeline.Workspace)/.gradle

steps:
- task: Cache@2
  inputs:
    key: 'gradle | "$(Agent.OS)" | **/build.gradle.kts' # Swap build.gradle.kts for build.gradle when using Groovy
    restoreKeys: |
      gradle | "$(Agent.OS)"
      gradle
    path: $(GRADLE_USER_HOME)
  displayName: Configure gradle caching

- task: Gradle@2
  inputs:
    gradleWrapperFile: 'gradlew'
    tasks: 'build'
    options: '--build-cache'
  displayName: Build

- script: |   
    # stop the Gradle daemon to ensure no files are left open (impacting the save cache operation later)
    ./gradlew --stop    
  displayName: Gradlew stop
  • restoreKeys: 主キーが失敗した場合のフォールバック キー (省略可能)

Note

キャッシュは不変であり、特定のスコープ (ブランチ) に対して特定のキーを持つキャッシュが作成されると、キャッシュを更新できません。 つまり、キーが固定値の場合、同じブランチの後続のビルドはすべて、キャッシュの内容が変更された場合でもキャッシュを更新できません。 固定キー値を使用する場合は、フォールバック オプションとして 引数を restoreKeys 使用する必要があります。

Maven

Maven には、ダウンロードとビルドされた成果物を格納するローカル リポジトリがあります。 有効にするには、 オプションを maven.repo.local の下 $(Pipeline.Workspace) のパスに設定し、このフォルダーをキャッシュします。

:

variables:
  MAVEN_CACHE_FOLDER: $(Pipeline.Workspace)/.m2/repository
  MAVEN_OPTS: '-Dmaven.repo.local=$(MAVEN_CACHE_FOLDER)'

steps:
- task: Cache@2
  inputs:
    key: 'maven | "$(Agent.OS)" | **/pom.xml'
    restoreKeys: |
      maven | "$(Agent.OS)"
      maven
    path: $(MAVEN_CACHE_FOLDER)
  displayName: Cache Maven local repo

- script: mvn install -B -e

Maven タスクを使用している場合は、変数が上書きされるため、必ず変数を渡MAVEN_OPTSしてください。

- task: Maven@4
  inputs:
    mavenPomFile: 'pom.xml'
    mavenOptions: '-Xmx3072m $(MAVEN_OPTS)'

.NET/NuGet

を使用PackageReferencesしてプロジェクト ファイル内で NuGet の依存関係を直接管理し、ファイルがあるpackages.lock.json場合は、環境変数を の$(UserProfile)パスに設定NUGET_PACKAGESし、このディレクトリをキャッシュすることで、キャッシュを有効にすることができます。 依存関係をロックする方法の詳細については、「 プロジェクト ファイルのパッケージリファレンス」を参照 してください。 複数の packages.lock.json を使用する場合でも、変更を加えずに次の例を使用できます。 すべての packages.lock.json ファイルの内容がハッシュされ、いずれかのファイルが変更されると、新しいキャッシュ キーが生成されます。

:

variables:
  NUGET_PACKAGES: $(Pipeline.Workspace)/.nuget/packages

steps:
- task: Cache@2
  inputs:
    key: 'nuget | "$(Agent.OS)" | $(Build.SourcesDirectory)/**/packages.lock.json'
    restoreKeys: |
       nuget | "$(Agent.OS)"
       nuget
    path: $(NUGET_PACKAGES)
  displayName: Cache NuGet packages

/npm のNode.js

Node.js プロジェクトでキャッシュを有効にする方法はさまざまですが、npm の 共有キャッシュ ディレクトリをキャッシュすることをお勧めします。 このディレクトリは npm によって管理され、ダウンロードされたすべてのモジュールのキャッシュ されたバージョンが含まれています。 インストール時に、npm は、パブリック npm レジストリまたはプライベート レジストリへのネットワーク呼び出しを削減または排除できるモジュールについて、最初に (既定で) このディレクトリをチェックします。

npm の共有キャッシュ ディレクトリへの既定のパスはすべてのプラットフォームで同じではないので、 の下$(Pipeline.Workspace)のパスに環境変数をnpm_config_cacheオーバーライドすることをお勧めします。 これにより、コンテナー ジョブとコンテナー以外のジョブからキャッシュにアクセスできるようになります。

:

variables:
  npm_config_cache: $(Pipeline.Workspace)/.npm

steps:
- task: Cache@2
  inputs:
    key: 'npm | "$(Agent.OS)" | package-lock.json'
    restoreKeys: |
       npm | "$(Agent.OS)"
    path: $(npm_config_cache)
  displayName: Cache npm

- script: npm ci

プロジェクトにファイルがない場合は package-lock.json 、代わりにキャッシュ キー入力内のファイルを参照 package.json します。

ヒント

フォルダーをnode_modules削除して、一貫性のある反復可能なモジュールセットが使用されるようにするためnpm ci、 を呼び出npm ciすときはキャッシュをnode_modules避ける必要があります。

Node.js/Yarn

npm と同様に、Yarn と共にインストールされたパッケージをキャッシュする方法はさまざまです。 推奨される方法は、Yarn の 共有キャッシュ フォルダーをキャッシュすることです。 このディレクトリは Yarn によって管理され、ダウンロードされたすべてのパッケージのキャッシュ されたバージョンが含まれています。 インストール時に、Yarn はこのディレクトリを最初に (既定で) モジュール用にチェックします。これにより、パブリック レジストリまたはプライベート レジストリへのネットワーク呼び出しを削減または排除できます。

:

variables:
  YARN_CACHE_FOLDER: $(Pipeline.Workspace)/.yarn

steps:
- task: Cache@2
  inputs:
    key: 'yarn | "$(Agent.OS)" | yarn.lock'
    restoreKeys: |
       yarn | "$(Agent.OS)"
       yarn
    path: $(YARN_CACHE_FOLDER)
  displayName: Cache Yarn packages

- script: yarn --frozen-lockfile

Python/Anaconda

Anaconda 環境を使用してパイプライン キャッシュを設定します。

variables:
  CONDA_CACHE_DIR: /usr/share/miniconda/envs

# Add conda to system path
steps:
- script: echo "##vso[task.prependpath]$CONDA/bin"
  displayName: Add conda to PATH

- bash: |
    sudo chown -R $(whoami):$(id -ng) $(CONDA_CACHE_DIR)
  displayName: Fix CONDA_CACHE_DIR directory permissions

- task: Cache@2
  displayName: Use cached Anaconda environment
  inputs:
    key: 'conda | "$(Agent.OS)" | environment.yml'
    restoreKeys: | 
      python | "$(Agent.OS)"
      python
    path: $(CONDA_CACHE_DIR)
    cacheHitVar: CONDA_CACHE_RESTORED

- script: conda env create --quiet --file environment.yml
  displayName: Create Anaconda environment
  condition: eq(variables.CONDA_CACHE_RESTORED, 'false')
  • Windows

    - task: Cache@2
      displayName: Cache Anaconda
      inputs:
        key: 'conda | "$(Agent.OS)" | environment.yml'
        restoreKeys: | 
          python | "$(Agent.OS)"
          python
        path: $(CONDA)/envs
        cacheHitVar: CONDA_CACHE_RESTORED
    
    - script: conda env create --quiet --file environment.yml
      displayName: Create environment
      condition: eq(variables.CONDA_CACHE_RESTORED, 'false')
    

PHP/Composer

Composer を使用する PHP プロジェクトの場合は、Composer で使用される COMPOSER_CACHE_DIR環境変数 をオーバーライドします。

:

variables:
  COMPOSER_CACHE_DIR: $(Pipeline.Workspace)/.composer

steps:
- task: Cache@2
  inputs:
    key: 'composer | "$(Agent.OS)" | composer.lock'
    restoreKeys: |
      composer | "$(Agent.OS)"
      composer
    path: $(COMPOSER_CACHE_DIR)
  displayName: Cache composer

- script: composer install

既知の問題とフィードバック

パイプラインのキャッシュの設定で問題が発生している場合は、リポジトリで 開いている問題 の一覧を microsoft/azure-pipelines-tasks 確認してください。 問題が一覧に表示されない場合は、新しい問題を 作成 し、シナリオに関する必要な情報を提供します。

Q&A

Q: キャッシュをクリアできますか?

A: キャッシュのクリアは現在サポートされていません。 ただし、既存のキャッシュ キーに文字列リテラル (など version2) を追加して、既存のキャッシュにヒットしないようにキーを変更できます。 たとえば、次のキャッシュ キーをこのキーから変更します。

key: 'yarn | "$(Agent.OS)" | yarn.lock'

変更後は次のようになります。

key: 'version2 | yarn | "$(Agent.OS)" | yarn.lock'

Q: キャッシュの有効期限はいつですか?

A: キャッシュは、アクティビティがない 7 日後に期限切れになります。

Q: キャッシュはいつアップロードされますか?

A: パイプラインの最後の手順の後、キャッシュがキャッシュ path から作成され、アップロードされます。 詳細については、 この例 を参照してください。

Q: キャッシュのサイズに制限はありますか?

A: 個々のキャッシュのサイズや組織内のすべてのキャッシュの合計サイズに制限は適用されません。