SpringBootアプリケーションをCloudNativeBuildpacksでコンテナ化する方法

# はじめに

近年、アプリケーション開発では「コンテナ化」が標準的な手法となっています。

たとえば、Spring Boot のようなクラウドネイティブなフレームワークを使用すれば、コンテナ化のプロセスがより効率的になり、開発から運用まで高品質なコンテナ化アプリケーションの提供が可能になります。

しかし、従来の Dockerfile を使用したコンテナ化には課題がありました。本記事では、これらの課題を解決し、より効率的に Spring Boot アプリケーションをコンテナ化する方法を紹介します。

# Dockerfile を使用したコンテナ化の課題

従来の Dockerfile を使用したコンテナイメージの作成・運用には、以下のような課題がありました

**1. セキュリティリスク**

- ベースイメージやライブラリの脆弱性管理
- セキュリティアップデートの煩雑さ

**2. 最適化の難しさ**

- 効率的なレイヤー構造設計の複雑さ
- イメージサイズの肥大化

**3. 標準化の困難さ**

- 組織内での Dockerfile 作成プラクティスの統一
- 個人のスキルへの依存

**4. 高いメンテナンスコスト**

- Dockerfile の定期的な更新や最適化の手間
- 最新のベストプラクティスへの追従

これらの課題を解決するのが、**Cloud Native Buildpacks (CNB)** です。

CNB は、アプリケーションのソースコードからコンテナイメージを自動的に作成するツールです。開発者は CNB を使用することで、アプリケーションのソースコードだけ用意すれば、以下の作業を自動化することができるのです。

- **最適なベースイメージとライブラリの選択**
- **アプリケーションコードと依存ライブラリの効率的なレイヤー分離**
- **最適化された Docker イメージのビルド**

# Spring Boot と CNB の統合

`Spring Boot 2.3` 以降では、Maven と Gradle の両方に対する CNB が標準でサポートされています。

そのため、Spring Boot アプリケーションの開発者はコマンドを 1 つ入力するだけで、簡単に最適化されたコンテナイメージを作成することができます。

# コンテナイメージをビルドする手順

以降では、Spring Boot (Gradle) プロジェクトで CNB を活用して、効率的にコンテナイメージをビルドする手順を説明します。

Gradle を利用したプロジェクトで CNB を使ってコンテナイメージを作成するには `bootBuildImage` タスクを利用します。

## 1. 事前準備

### 1.1 Gradle プロジェクトの設定

`bootBuildImage` タスクは `bootJar` タスクの出力を使用するため、プロジェクトには以下のように `java` プラグインが適用されている必要があります。

```gradle:build.gradle
plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.5'
}
```

### 1.2 Docker 環境の準備

`bootBuildImage` タスクは Docker デーモンへのアクセスを必要とします。
そのため、**Docker がインストールされていること**、そして **Docker デーモンが起動されていること**を確認してください。

Docker の状態は以下のコマンドで確認できます。

```
$ docker info
```

## 2. イメージの作成

準備が整ったら、以下のコマンドで `bootBuildImage` タスクを実行して、コンテナイメージをビルドします。

`bootBuildImage` タスクは、以下のコマンドで実行できます。

```bash
$ ./gradlew bootBuildImage
```

処理中は、進捗状況がコンソールに表示されます。

※ 最初は数分かかる可能性があります。

### カスタマイズ

`bootBuildImage` タスクは基本的にデフォルトの設定で実行できますが、必要に応じてカスタマイズすることもできます。

たとえば、イメージ名を指定する場合は、以下を `build.gradle` に追記します。

```gradle:build.gradle
tasks.named("bootBuildImage") {
    imageName = 'demo:0.0.1-SNAPSHOT'
}
```

この設定はコマンドライン引数で行うこともできます。

```bash
$ ./gradlew bootBuildImage --imageName=demo:0.0.1-SNAPSHOT
```

他にも、ベースイメージの指定や Docker ホストの指定など、様々なオプションを設定可能です。

### イメージの確認

イメージのビルドが完了したら、`docker images` コマンドで新しいイメージが作成されたことを確認できます。

```bash
$ docker images

REPOSITORY       TAG                  IMAGE ID       CREATED             SIZE
demo             0.0.1-SNAPSHOT       edd8f...       4 seconds ago       300MB
```

## 3. コンテナの実行

作成したイメージからコンテナを実行するには、`Docker run` コマンドを実行します。

```bash
$ docker run -p 8080:8080 demo:0.0.1-SNAPSHOT
```

ここでは、`-p 8080:8080` オプションによってコンテナ内の `8080` ポートをホストマシンの `8080` ポートにマッピングしています。

Spring Boot アプリケーションが正常に起動すると、コンソールに起動ログが表示されます。
起動完了後、ブラウザで http://localhost:8080 にアクセスして、アプリケーションが正常に動作していることを確認できれば完了です。

# さいごに

以上、CNB を使って Spring Boot アプリケーションのコンテナイメージをビルドする方法を紹介しました。

アプリケーションのコンテナ化は避けて通れない道となっていますが、CNB によって開発者は最小限の手間でベストプラクティスに沿ったセキュアで最適化された Docker イメージを自動構築できます。

特に Spring Boot では CNB の導入が非常に簡単ですので、ぜひ活用されてみてはいかがでしょうか。

# 参考

▼ [Cloud Native Buildpacks :: Spring Boot - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-boot/reference/packaging/container-images/cloud-native-buildpacks.html)
▼ [OCI イメージのパッケージ化 :: Spring Boot - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-boot/gradle-plugin/packaging-oci-image.html)
▼ [Configuring Gradle Tasks in Spring Boot 3 | Baeldung](https://www.baeldung.com/spring-boot-3-gradle-configure-tasks#build-image)
▼ [Dockerfile の属人化による脆弱性を防げ　ベストなイメージが作成可能な Cloud Native Buildpacks の使い方 - ログミー Tech (logmi.jp)](https://logmi.jp/tech/articles/324447)