Buildpacks が Google Cloud で使える件

## はじめに
こんにちは、Datadog Japan で Sales Engineer をしている [**AoTo**](https://qiita.com/AoTo0330) です。

この記事は **[<font color="#6495ED">AoTo Advent Calendar 2023</font>](https://qiita.com/advent-calendar/2023/aoto) 26日目**の記事改め、**[<font color="##0F9D58">GCP(Google Cloud Platform) Advent Calendar 2023</font>](https://qiita.com/advent-calendar/2023/gcp) 7日目**の記事です。

皆さんは [**Cloud Native Buildpacks**](https://buildpacks.io/) をご存知でしょうか？**Buildpacks** は **Dockerfile** を書くことなく、ソース コードから安全で効率的な、本番環境に対応したコンテナイメージを作成できるツールです。

この便利な Buildpacks が Google Cloud でも手軽に利用できるので、何ができるかまとめてみました。

## Cloud Native Buildpacks とは
### 概要
[Buildpack](https://www.heroku.com/elements/buildpacks) は2011年に Heroku によって考案され、現在では Cloud Foundry, Google App Engine, Gitlab, Knative, Deis Dokku, Drie など他の PaaS に採用されています。

Heroku と Pivotal は2018年10月に Buildpacks を Cloud Native Computing Foundation の[プロジェクト]として開始し、ビルドパックの統合を CNCF コミュニティによって維持するようになりました。

[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2363567/6fe0efe4-8c8f-d3f0-a84d-4182c53613f3.png)
](https://buildpacks.io/)

こうして誕生した [**Cloud Native Buildpacks**](https://buildpacks.io/) は、OCI イメージ形式などの最新のコンテナ標準を採用しています。

### 概念
**Buildpacks** はソース コードから安全で効率的な、本番環境に対応したコンテナイメージを作成できるツールです。

[![image.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2363567/99f3ede5-676e-2003-7e9a-49bc400d4715.jpeg)
](https://buildpacks.io/docs/concepts/)

こうしたコンテナイメージの作成は`detect`と`build`フェーズを通して行われ、アプリケーションに必要なフレームワークとランタイムを提供してクラウド上で実行できるよう適切に構成を行います。

`detect`フェーズでは、ソースコードを検査し buildpack が適用できるかを判断します。

`build`フェーズでは、ソースコードを確認し依存関係のダウンロードやコンパイル(言語による)を行います。さらにエントリーポイントと起動スクプトを設定し、コンテナイメージをビルド環境を用いてビルドします。

この際、必要となるのが [**builder**](https://buildpacks.io/docs/concepts/components/builder/) です。**builder** はビルドの実行に必要なすべてのコンポーネントを含むイメージで、[build image](https://buildpacks.io/docs/concepts/components/base-images/build/), [lifecycle](https://buildpacks.io/docs/concepts/components/lifecycle/), [run image](https://buildpacks.io/docs/concepts/components/base-images/run/), [buildpack](https://buildpacks.io/docs/concepts/components/buildpack/) やこれらの順序や場所を定義するファイルによって構成されます。

[![image2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2363567/dcd47971-1f29-36a1-8771-0736d31f615f.jpeg)](https://buildpacks.io/docs/concepts/#what-are-buildpacks)

### 特徴
Buildpacks の基本的な概念は Dockerfile を利用しないソースコードからのコンテナイメージのビルドですが、その他にも重要な特徴や役割があります。

#### Dockerfile
Buildpacks は`root`ユーザーとしては実行されないため、ファイルシステムに任意の変更ができません。そのため、OS パッケージのように特権が必要となる構成を行えません。

Buildpacks を Dockerfile と併用して利用することで、これらの OS レベルの依存関係を Dockerfile で提供しながら Buildpack でコンテナイメージを作成することができます。

[イメージ拡張機能](https://buildpacks.io/docs/features/dockerfiles/#what-are-image-extensions)を利用すると`detect`フェーズでアプリケーションコードの分析を経て Dockerfile を生成して OS レベルの依存関係を構成することができます。

#### SBoM
[Software Bill of Materials(SBoM)](https://buildpacks.io/docs/features/bill-of-materials/) により、イメージに含まれるすべてのソフトウェアコンポーネントをリストできます。CycloneDX, Syft, Spdx形式の SBoM がサポートされています。

```zsh
$ pack sbom download <YOUR_IMAGE_NAME>
```


## Google Cloud の Buildpacks
[Google Cloud で公開されている Buildpacks](https://cloud.google.com/docs/buildpacks/overview) は、前述の Cloud Native Buildpacks の仕様を実装し、Google Cloud の各サービスにデプロイ可能なコンテナをビルドして構成するように設計されています。

Google Cloud の Buildpacks は Google Cloud 上のサービス用に専用のビルダーと環境変数を用いた構成を提供しています。公式のガイドでは自前の環境へのインストールが案内されていますが、[**Google Cloud Shell**](https://cloud.google.com/shell) には標準でインストールされています。

```zsh
$ pack version
0.21.1+git-e09e397.build-2823
```

[**Google Cloud Workstations**](https://cloud.google.com/workstations) には標準でのインストールがないため、以下のように pack-cli をインストールします。

```zsh
$ sudo add-apt-repository ppa:cncf-buildpacks/pack-cli
$ sudo apt-get update
$ sudo apt-get install pack-cli
```


### 汎用ビルダー
[汎用ビルダー](https://cloud.google.com/docs/buildpacks/builders)は Google Cloud に限らない環境で利用できるコンテナイメージを作成するデフォルトのビルダーです。

汎用ビルダー自体は Google Container Registry(GCR) に一般公開されている、Ubuntu ベースのコンテナイメージで、現在は Ubuntu 22 をベースとしたもの(`google-22`)が`latest`となっています。


アプリケーション言語に応じて複数のバージョンをサポートしており、Python(3.10.X, 3.11.X), Node.js(12.X.X, 14.X.X, 16.X.X, 18.X.X, 20.X.X), Java(8, 11, 17, 18), Go(1.X), Ruby(3.1.X, 3.2.X), PHP(8.1.X, 8.2.X), .NET Core(6.X, 7.X) がサポートされます。[^1]
[^1]: Java 8 はアプリケーションのみでサポートされます。

### App Engine
Google Cloud の Buildpacks は Google App Engine(GAE) [第2世代ランタイム](https://cloud.google.com/appengine/docs/standard/runtimes)のアプリケーションをコンテナ化するための[専用のビルダー](https://cloud.google.com/docs/buildpacks/builders)を公開しています。サポートされるアプリケーション言語とバージョンは App Engine に対応しています。

このビルダーには Ubuntu18, 22 をベースとして追加の buildpack と App Engine 固有の構成が含まれており、実行速度や自動更新の最適化が行われます。それぞれ、`gcr.io/gae-runtimes/buildpacks/google-gae-18/<application_lang>/builder`か`gcr.io/gae-runtimes/buildpacks/google-gae-22/<application_lang>/builder`を [Builder Image URL に指定する](https://cloud.google.com/docs/buildpacks/use-a-specific-builder)だけで利用できます。

```zsh
$ pack build SERVICE_IMAGE_NAME --builder=<BUILDER_IMAGE_URL>
```

### Cloud Run
環境変数により　Cloud Run, Cloud Functions にデプロイされた時のサービスの動作を構成できます。複数のアプリケーションが動作しているコンテナの制御し適切な `ENTRYPOINT` を設定したり、ランタイムとそのバージョンを指定できるため、稼働する環境に最適化してある程度自由にコンテナイメージを作成できます。

| 環境変数名 | 説明 |
| -- | -- |
| [`GOOGLE_ENTRYPOINT`](https://cloud.google.com/docs/buildpacks/service-specific-configs#google_entrypoint) | Dockerfile の `ENTRYPOINT` と同様に、コンテナの実行時に実行されるコマンドを指定します |
| [`GOOGLE_RUNTIME`](https://cloud.google.com/docs/buildpacks/service-specific-configs#google_runtime) | ランタイムを強制的に指定できます |
| [`GOOGLE_RUNTIME_VERSION`](https://cloud.google.com/docs/buildpacks/service-specific-configs#google_runtime_version) | ランタイムのバージョンを指定できます |
| [`GOOGLE_BUILDABLE`](https://cloud.google.com/docs/buildpacks/service-specific-configs#google_buildable) | Go, Java, Dart, .NET で、ビルド可能ユニットへのパスを指定できます |
| [`GOOGLE_BUILD_ARGS`](https://cloud.google.com/docs/buildpacks/service-specific-configs#google_build_args) | Java(Maven, Gradle) と .NET で、ビルドコマンドに引数を追加できます |
| [`GOOGLE_MAVEN_BUILD_ARGS`](https://cloud.google.com/docs/buildpacks/service-specific-configs#google_maven_build_args) | Java(Maven) で、Maven コマンドをオーバーライドできます <br>`mvn clean package --batch-mode -DskipTests -Dhttp.keepAlive=false` がデフォルトで実行されます|
| [`GOOGLE_GRADLE_BUILD_ARGS`](https://cloud.google.com/docs/buildpacks/service-specific-configs#google_gradle_build_args) | Java(Gradle)で、Gracle コマンドをオーバーライドできます <br>`gradle clean assemble -x test --build-cache`がデフォルトで実行されます |
| [`GOOGLE_DEVMODE`](https://cloud.google.com/docs/buildpacks/service-specific-configs#google_devmode) | [**Skaffold**](https://skaffold.dev/)(開発モードの Buildpack) を有効にします。**Skaffold** のインストール、skaffold dev を実行する必要があります |
| [`GOOGLE_CLEAR_SOURCE`](https://cloud.google.com/docs/buildpacks/service-specific-configs#google_clear_source) | Go, Java か Functions で、アプリケーションビルド後にソースをクリアします |


### Cloud Functions
上記の Cloud Run に共通の環境変数の他に、Cloud Function 固有の環境変数が用意されています。

| 環境変数名 | 説明 |
| -- | -- |
| [`GOOGLE_FUNCTION_TARGET`](https://cloud.google.com/docs/buildpacks/service-specific-configs#google_function_target) | リクエストに応じて関数を呼び出せます |
| [`GOOGLE_FUNCTION_SIGNATURE_TYPE`](https://cloud.google.com/docs/buildpacks/service-specific-configs#google_function_signature_type) | 関数で使用される署名を指定できます |
| [`GOOGLE_FUNCTION_SOURCE`](https://cloud.google.com/docs/buildpacks/service-specific-configs#google_function_source) | 言語に応じたディレクトリ・ファイルの名前を指定できます |

## おわりに
Google Cloud でコンテナイメージを扱うようなGoogle Kubernetes Engine(GKE), Cloud Run, App Engine(GAE), Cloud Functions などに利用するコンテナイメージを Buildpack で作成できます。

Google Cloud は App Engine 用のビルダーや Cloud Run, Cloud Function 用の環境変数を提供しているため、これらのサービスを利用する場合は一度確認しておくと良いように思います。