Cloud Native BuildpacksでビルドしたSpring Boot コンテナにてAPM agentを起動する方法

## はじめに

コンテナ環境でAPM agentをロードする際はDockerfile上のエントリーポイントで `-javaagent` VMオプションを指定してAgentをロードする方法が一般的です。
しかし、CNBs(Cloud Native Buildpacks)でビルドすると、Dockerfileを書かないため方法が異なります。これに関する分かりやすいドキュメントが見当たらなかったため本記事にて紹介します。


## Spring BootアプリケーションでCNBビルドの確認
まず、Spring Bootアプリケーションをセットアップします。すでにSpring Bootアプリケーションがある場合はスキップして構いません。[Spring Initializr](https://start.spring.io/)を使用してSpring Bootプロジェクトを生成できます。
セットアップしたら、Gradleであれば次のコマンドで buildpack にてDockerイメージをビルドできます：`./gradlew buildBootImage`
これだけで docker imageがビルドできます。

## Spring Boot CNB でAgentの読み込み方法

最終的にやることは基本的に　`task: buildBootImage`の修正ぐらいです。

Azure Application Insights agentをロードする例のソースコードは[ここ](https://github.com/toyopilgrim/sample-application-insights-buildpack)に置きました。

Application Insightsを例にしますが、豊富なagentが対応されています。

[paketo-buildpacks/apache-skywalking](https://github.com/paketo-buildpacks/apache-skywalking)
[paketo-buildpacks/azure-application-insights](https://github.com/paketo-buildpacks/azure-application-insights)
[paketo-buildpacks/datadog](https://github.com/paketo-buildpacks/datadog)
[paketo-buildpacks/new-relic](https://github.com/paketo-buildpacks/new-relic)

などなど。

早速、Gradleの修正を解説します。
今回の例では [paketo-buildpacks/azure-application-insights](https://github.com/paketo-buildpacks/azure-application-insights)を使用します。

### バインディングディレクトリを作成する

任意の場所で良いのですが、プロジェクトのルートが一般的です。
gradle.build から以下の参照ができるようにディレクトリを作成。
```
$projectDir/bindings/application-insights
```

次に、"type" という名前の拡張子なしのファイルを作成します。このファイルはビルドパックがバインディングを識別できるようにするため重要です。
type ファイルの中には　ApplicationInsights　と記載。[例](https://github.com/toyopilgrim/sample-application-insights-buildpack/blob/main/bindings/application-insights/type)


### Gradle taskの修正

以下のタスクを gradle.buildに追加。
```Gradle
tasks.named("bootBuildImage") {
	buildpacks = [
			"urn:cnb:builder:paketo-buildpacks/java",
			"gcr.io/paketo-buildpacks/azure-application-insights"
	]
	bindings = [file('bindings/application-insights').absolutePath + ":/platform/bindings/application-insights"]
}
```

- buildpacksにて"gcr.io/paketo-buildpacks/azure-application-insights"を追加
- bindingsにて、コンテナ内の/platform/bindings/application-insightsに$projectDir/bindings/application-insights（ホストで以前に作成されたもの）をマウント

Paketo Buildpacksはビルド時に/platform/bindingsディレクトリ内でバインディングを検索するため、後者のパスは変更しないでください。

Gradle taskの修正は以上です。


### APPLICATIONINSIGHTS_CONNECTION_STRINGの設定

application.propertiesでApplication Insightsのconnection stringを設定。
`APPLICATIONINSIGHTS_CONNECTION_STRING=${APPINSIGHTS_CONNECTION_STRING}`


### 実行確認

```bash
./gradlew buildBootImage
```

ビルド中にtypeがApplicationInsightsと正しく識別される場合、次のような出力が表示されます。
```
[creator] Paketo Buildpack for Azure Application Insights 5.21.0
[creator] https://github.com/paketo-buildpacks/azure-application-insights
[creator] Azure Application Insights Java Agent 3.5.2:
```

これによって APM agentの起動完了です。


## 例以外のビルドパックの設定について

基本的に同じです。例えばSkywalkingだと

`/buildSrc/bindings/skywalking/type`に　"ApacheSkyWalking"をセット。

Gradleは以下のように修正。
```
    buildpacks = ["urn:cnb:builder:paketo-buildpacks/java",
                  "gcr.io/paketo-buildpacks/apache-skywalking"
    ]
    bindings = [file('../../buildSrc/bindings/skywalking').absolutePath + ":/platform/bindings/skywalking"]
```


以上、Spring Boot CNB　のAPM agent起動方法でした。