パイプライン キャッシュ
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.json
yarn.lock
Gemfile.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: 個々のキャッシュのサイズや組織内のすべてのキャッシュの合計サイズに制限は適用されません。