GCPのCI/CDサービスであるCloudBuildで、特定のディレクトリをCacheして高速化する方法です。
node_modulesのcacheを例として説明しますが、他の言語でも何でもいけるはずです。
Cloud Build: サーバーレス CI / CD プラットフォーム | Google Cloud
CloudBuildでの高速化方法
公式ドキュメントでいくつか紹介されています。
ビルドを高速化する際のおすすめの方法 | Cloud Build のドキュメント | Google Cloud
今回は、「Google Cloud Storage でのディレクトリのキャッシュ」についての説明です。
対象のプロジェクト
javascriptでの静的ページなプロジェクトを想定して説明します。
reactやvueでのSPAなイメージです。
steps:
- name: node
entrypoint: npm
args: ['install']
dir: app
- id: 'generate'
name: 'node'
args: ['npm', 'run', 'generate']
dir: app
# deploy(省略)
使用しているライブラリが多いと、npm install
(あるいはyarn install
)にかなり時間がかかる場合があります。
そこで、node_modules
ディレクトリをcacheして高速化します。
appディレクトリ配下にnode_modules
が作成されるものとします。
cacheの設定
事前準備
cacheファイルを保存しておくCloud Storageのbucketを作成しておきます。
ここではcloud-build-cache
という名前で作った事にします。
cloudbuild.yamlの例
steps:
# cacheファイルを取得
- name: gcr.io/cloud-builders/gsutil
args: ['cp', 'gs://cloud-build-cache/cache.tar.gz', 'app/cache.tar.gz']
# cacheファイルを解凍
- name: bash
args: ['tar', 'xzf', 'app/cache.tar.gz']
- name: node
entrypoint: npm
args: ['install']
dir: app
- id: 'generate'
name: 'node'
args: ['npm', 'run', 'generate']
dir: app
# deploy(省略)
# zip化
- name: bash
id: 'archive node_modules'
args: ['tar', 'czf', 'cache.tar.gz', 'app/node_modules']
waitFor: [ 'generate' ]
# upload
- name: gcr.io/cloud-builders/gsutil
args: ['cp', 'cache.tar.gz', 'gs://cloud-build-cache/cache.tar.gz',]
waitFor: [ 'archive node_modules' ]
解説
まず、CloudStorageを保存するファイルは、対象ディレクトリをzip化したファイルにしています。
他の選択肢としては、
- zip化せずにcpコマンドでディレクトリ毎コピー
- rsyncで差分コピー
が考えられますが、node_modulesはファイル数がかなり多くなりがちで、1ファイルずつの対応はかなり時間がかかる可能性があります。(私の手元の環境では5万ファイルが対象で、いつまでたってもアップロードが終わりませんでした)
cacheファイルを取得とupload
# cacheファイルを取得
- name: gcr.io/cloud-builders/gsutil
args: ['cp', 'gs://cloud-build-cache/cache.tar.gz', 'app/cache.tar.gz']
# upload
- name: gcr.io/cloud-builders/gsutil
args: ['cp', 'cache.tar.gz', 'gs://cloud-build-cache/cache.tar.gz',]
waitFor: [ 'archive node_modules' ]
CloudBuildでは、gsutilというCloudStorageを扱うコマンドが簡単に使えるようになっています。
今回使っているのはcp
コマンドで、ローカル(今回だとCloudBuild上のディレクトリ) ⇔ CloudStorage
のファイルのやり取りをする事ができます。
cp - Copy files and objects | Cloud Storage | Google Cloud
圧縮と解凍
# cacheファイルを解凍
- name: bash
args: ['tar', 'xzf', 'app/cache.tar.gz']
# zip化
- name: bash
id: 'archive node_modules'
args: ['tar', 'czf', 'cache.tar.gz', 'app/node_modules']
waitFor: [ 'generate' ]
普通のlinuxコマンドです。
結果
プロジェクトの構成によって大きく変わると思いますが、私の環境だと
- 対応前 -> 10分ほど
- 対応後(cacheが効いている場合) -> 6分ほど
に高速化する事ができました。たかが4分、されど4分。
ライブラリのインストールに時間がかかっている場合は、検討する価値はありそうです。