Kaniko キャッシュの使用

概要

Kaniko キャッシュは、コンテナビルドのアーティファクトをキャッシュに保存します。キャッシュ保存の際は、コンテナ イメージ レジストリ(Google 独自の Artifact Registry など)内の中間レイヤが保存され、インデックス付けされます。その他のユースケースについては、GitHub の Kaniko リポジトリをご覧ください。

Kaniko キャッシュの仕組みは次のとおりです。

  • Cloud Build では、コンテナ イメージのレイヤがビルド時にレジストリに直接アップロードされるため、明示的な push ステップはありません。すべてのレイヤが正常にビルドされると、それらレイヤを含むイメージ マニフェストがレジストリに書き込まれます。

  • Kaniko では、各レイヤが、その作成元の Dockerfile ディレクティブと、先行するすべてのディレクティブ(FROM 行のイメージのダイジェストに至るまでのもの)のコンテンツに従ってキャッシュに保存されます。

ビルドでの Kaniko キャッシュの有効化

Docker ビルドで Kaniko キャッシュを有効にするには、次に示すように、cloudbuild.yaml ファイルで cloud-builders/docker ワーカーを kaniko-project/executor ワーカーに置き換えます。

Kaniko ビルド

steps:
- name: 'gcr.io/kaniko-project/executor:latest'
  args:
  - --destination=${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/${_IMAGE}
  - --cache=true
  - --cache-ttl=XXh

Docker ビルド

steps:
- name: gcr.io/cloud-builders/docker
  args: ['build', '-t', '${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/${_IMAGE}', '.']
images:
- '${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/${_IMAGE}'

ここで

  • --destination=${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/${_IMAGE} は、ターゲットのコンテナ イメージです。Cloud Build は、Dockerfile を含むプロジェクトの PROJECT_ID を自動的に置き換えます。LOCATIONREPOSITORYIMAGEユーザー定義の置換です。
  • LOCATION は、イメージが保存されているリポジトリのリージョンまたはマルチリージョンのロケーションです(例: us-east1)。
  • REPOSITORY は、イメージが保存されるリポジトリの名前です。
  • IMAGE はイメージの名前です。
  • --cache=true は、Kaniko キャッシュを有効化します。
  • --cache-ttl=XXh でキャッシュの有効期限を設定します。ここで、XX はキャッシュの有効期限までの時間です。キャッシュ保存の有効期限の構成をご覧ください。

gcloud builds submit --tag [IMAGE] コマンドを使用してビルドを実行する場合、次に示すようにプロパティ builds/use_kanikoTrue に設定することで Kaniko キャッシュを有効化できます。

gcloud config set builds/use_kaniko True

例: Node.js ビルドでの Kaniko キャッシュの使用

次の例では、Dockerfile に関して一般的に推奨されている方法を使用して Node.js アプリの差分ビルドを実行する方法を示しています。ここに示す方法は、サポートされている他のすべての言語のビルドにも適用されます。

ここでは、ビルド間で変更される可能性が低いディレクティブを Dockerfile の先頭に移動し、変更される可能性の高いディレクティブを末尾に移動します。これによってビルドプロセスでの差分処理が効率化され、ビルドを迅速化できます。

ここでは次の Dockerfile について考えてみます。

FROM node:8
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
CMD [ "npm", "start" ]

この Dockerfile では次の処理が行われます。

このビルドを実行する際には、Cloud Build に複数のビルドを対象とするイメージレイヤのキャッシュが存在しないため、ビルドの実行のたびに Cloud Build で各ステップを実行しなければなりません。しかし、Kaniko キャッシュを有効にしてこのビルドを実行した場合は、以下の処理が行われます。

  1. 初回の実行時に Cloud Build によってすべてのステップが実行され、各ディレクティブによってレイヤがコンテナ イメージ レジストリに書き込まれます。

  2. Kaniko では、レイヤの作成元のディレクティブとそのすべての先行ディレクティブのコンテンツから導出されたキャッシュキーによるタグが、各レイヤに付けられます。

  3. それ以降、Cloud Build で同じ Dockerfile からビルドを実行するときは、そのファイルが変更されたかどうかが確認されます。変更されていない場合、Cloud Build ではレジストリに保存されているキャッシュ内のレイヤを使用してビルドが実施されるため、ビルドの完了までの時間が短縮されます。以下をご覧ください。

FROM node:8                # no change -> cached!
COPY package*.json ./      # no change -> cached!
RUN npm install            # no change -> cached!
COPY . .                   # no change -> cached!
CMD [ "npm", "start" ]     # metadata, nothing to do

package.json ファイルを変更した場合、内容が変更されていないため、COPY ステップの前に Cloud Build でディレクティブを実行する必要はありません。ただし、package.json ファイルの変更によって COPY ステップは変更されるため、COPY ステップの後のステップはすべて再実行する必要があります。以下をご覧ください。

FROM node:8                # no change -> cached!
COPY package*.json ./      # changed, must re-run
RUN npm install            # preceding layer changed
COPY . .                   # preceding layer changed
CMD [ "npm", "start" ]     # metadata, nothing to do

アプリの内容のみが変更され、依存関係が変更されない場合(よくあるシナリオ)には、package.json ファイルを変更せず、Cloud Build は最終版の COPY . . ステップのみを再実行する必要があります。この結果、このステップではソース コンテンツがコンテナ イメージ レジストリ内のレイヤにコピーされるだけなので、ビルドが迅速化されます。

FROM node:8                # no change -> cached!
COPY package*.json ./      # no change -> cached!
RUN npm install            # no change -> cached!
COPY . .                   # changed, must re-run
CMD [ "npm", "start" ]     # metadata, nothing to do

キャッシュ保存の有効期限の構成

--cache-ttl フラグは、キャッシュ内のレイヤのうち特定の有効期限内に push されなかったものを無視するよう Kaniko に指示します。

構文は --cache-ttl=XXh です。ここで、XX は時間(hr)です。たとえば、--cache-ttl=6h がキャッシュの有効期限を 6 時間に構成したとします。gcloud builds submit --tag [IMAGE] コマンドを使用してビルドを実行する場合、--cache-ttl フラグのデフォルト値は 6 時間です。Kaniko Executor イメージを直接使用する場合、デフォルト値は 2 週間です。

有効期限を長くすると、依存関係が頻繁に変更されない場合は、ビルドが迅速化されます。有効期限を短くすると、更新された依存関係(Maven パッケージや Node.js モジュール)がより迅速に取り込まれるものの、キャッシュ内のレイヤがあまり使用されなくなります。

キャッシュ保存の有効期限をコマンドラインから設定するには、次のコマンドを実行します。

gcloud config set builds/kaniko_cache_ttl XX

XX は、キャッシュ保存の有効期限(hr)です。

Node.js の例では、RUN npm install ディレクティブの出力は変わらないままであるため、キャッシュ保存されていても、このディレクティブを定期的に再実行する必要があります。--cache-ttl パラメータの 6 時間という設定はバランスのとれた値です。このディレクティブのコンテンツが変更されたかどうかに関係なく、営業日ごとに少なくとも 1 回はディレクティブが実行されるからです。ただし、ビルドの実行時に毎回実行されるわけではないのでシステムの負荷が軽減されます。