Dapr API から Spring Boot REST API にアクセスする (コンテナ編)

# Dapr API から Spring Boot REST API にアクセスする (コンテナ編)

こんにちは、@studio_meowtoon です。今回は、WSL Ubuntu 22.04 で Daprを Spring Boot コンテナのサイドカーとして連携する方法を紹介します。
![spring-boot_with_dapr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3206449/96405024-53a8-3626-3833-0c13340693ec.png)

## 目的

分散アプリケーションの為のランタイム [Dapr](https://docs.dapr.io/concepts/overview/) の理解を深めます。  

## 実現すること

Ubuntu の Docker 環境でコンテナとして起動した Spring Boot アプリに Dapr API からアクセスするシンプルな例を実装します。  

こちらの記事の続きになります。  

https://qiita.com/studio_meowtoon/items/2141cfd290b526a3bd39

## 開発環境

+ Windows 11 Home 22H2 を使用しています。  

:::note info
[WSL](https://learn.microsoft.com/ja-jp/windows/wsl/about) の Ubuntu を操作していきますので macOS の方も参考にして頂けます。  
::: 

<details>

WSL (Microsoft Store アプリ版) [※ こちらの関連記事からインストール方法をご確認いただけます](https://qiita.com/studio_meowtoon/items/2aaa6579cb8e4fa1d874)

```sh
> wsl --version
WSL バージョン: 1.0.3.0
カーネル バージョン: 5.15.79.1
WSLg バージョン: 1.0.47
```

Ubuntu [※ こちらの関連記事からインストール方法をご確認いただけます](https://qiita.com/studio_meowtoon/items/2aaa6579cb8e4fa1d874)

```sh
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 22.04.1 LTS
Release:        22.04
```

Java JDK [※ こちらの関連記事からインストール方法をご確認いただけます](https://qiita.com/studio_meowtoon/items/4d11e94a2389758759cd)

```sh
$ java -version
openjdk version "11.0.18" 2023-01-17
OpenJDK Runtime Environment (build 11.0.18+10-post-Ubuntu-0ubuntu122.04)
OpenJDK 64-Bit Server VM (build 11.0.18+10-post-Ubuntu-0ubuntu122.04, mixed mode, sharing)
```

Maven [※ こちらの関連記事からインストール方法をご確認いただけます](https://qiita.com/studio_meowtoon/items/f4cdc4039158153365fb)

```sh
$ mvn -version
Apache Maven 3.6.3
Maven home: /usr/share/maven
Java version: 11.0.18, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64
```

Docker [※ こちらの関連記事からインストール方法をご確認いただけます](https://qiita.com/studio_meowtoon/items/3bceee25ac67cc73ebbe)

```sh
$ docker --version
Docker version 23.0.1, build a5ee5b1
```

Dapr [※ こちらの関連記事からインストール方法をご確認いただけます](https://qiita.com/studio_meowtoon/items/a00f2802a171959b5728)

```sh
$ dapr --version
CLI version: 1.11.0
Runtime version: 1.11.2
```

</details>

※ この記事では基本的に Ubuntu のターミナルで操作を行います。

## 作成する Web アプリケーションの仕様

|No|エンドポイント|HTTPメソッド|MIME タイプ|
|:--|:--|:--|:--|
|1|/api/data|GET|application/json|

<details>
<summary>説明を開きます。</summary>

:::note info
**/api/data** という**エンドポイント**に対して **HTTP GET** リクエストを送信すると、**JSON データ**がレスポンスされるシンプルな Web サービスを実装します。
:::

</details>

## Dapr ランタイムを削除する

:::note warn
この記事では、docker-compose で立ち上げるコンテナ群で Dapr ランタイムを構成します。  
:::

Dapr ランタイムを削除します。

```sh
$ dapr uninstall --all
```

出力

```sh
ℹ️  Removing Dapr from your machine...
ℹ️  Removing directory: /home/$USER/.dapr/bin
ℹ️  Removing directory: /home/$USER/.dapr
✅  Dapr has been removed successfully
```

ランタイムを確認します。

```sh
$ dapr --version
CLI version: 1.11.0
Runtime version: n/a
```

:::note info
ここまでの手順で、Dapr ランタイムは削除されました。
:::

## Hello World を表示する手順

### Spring Boot WEBアプリの作成

前回の記事からご確認いただけます。

https://qiita.com/studio_meowtoon/items/2141cfd290b526a3bd39

プロジェクトフォルダに移動します。
※ ~/tmp/hello-spring-dapr をプロジェクトフォルダとします。

```sh
$ cd ~/tmp/hello-spring-dapr
```

Java アプリをビルドします。

```sh
$ mvn clean package
```

:::note info
ここまでの手順で、target/app.jar Java アプリが作成されました。
:::

### コンテナイメージをビルド

Dockerfile を作成します。

```sh
$ vim Dockerfile
```

ファイルの内容

```sh:Dockerfile
FROM adoptopenjdk/openjdk11:jdk-11.0.11_9-alpine-slim

WORKDIR /app

COPY target/*.jar app.jar

EXPOSE 8080

ENTRYPOINT ["java","-jar","app.jar"]
```

コンテナイメージをビルドします。

```sh
$ docker build -t app-hello-spring-boot .
```

確認

```sh
$ docker images | grep app-hello-spring-boot
app-hello-spring-boot   latest    2ee39bcf1346   11 seconds ago   278MB
```

:::note info
ここまでの手順で、app-hello-spring-boot コンテナイメージが作成されました。
:::

### docker-compose.yml の作成

docker-compose.yml ファイルを作成します。

```sh
$ vim docker-compose.yml
```

ファイルの内容

```yaml
version: '3'
services:
  ############################
  # Spring Boot app + Dapr sidecar
  app-spring:
    image: app-hello-spring-boot
    depends_on:
      - redis
      - placement
    ports:
      - "3500:3500"
    networks:
      - net-hello
  app-spring-dapr:
    image: daprio/daprd:edge
    command: [
      "./daprd",
      "--app-id", "app-hello-spring",
      "--app-port", "8080",
      "--dapr-http-port", "3500",
      "--dapr-grpc-port", "50051",
      "--placement-host-address", "placement:50006",
      "--components-path", "/components"
    ]
    volumes:
      - "./components/:/components"
    depends_on:
      - app-spring
    network_mode: "service:app-spring"
  ############################
  # Dapr placement service
  placement:
    image: daprio/dapr
    command: ["./placement", "-port", "50006"]
    ports:
      - "50006:50006"
    networks:
      - net-hello
  ############################
  # Redis state store
  redis:
    image: redis:alpine
    ports:
      - "6380:6379"
    networks:
      - net-hello
networks:
    net-hello:
```

:::note info
Dapr を Spring Boot アプリの**サイドカー**として設定しており、Spring Boot アプリのコンテナは 3500 番ポートでリッスンしています。  
:::

### Docker 環境で起動する

コンテナを起動します。

:::note warn
docker-compose がインストールされていない場合、以下のコマンドでインストールします。

```sh
$ sudo apt update
$ sudo apt install docker-compose
```
:::

```sh
$ docker-compose up -d
Creating hello-spring-dapr_placement_1 ... done
Creating hello-spring-dapr_redis_1     ... done
Creating hello-spring-dapr_app-spring_1 ... done
Creating hello-spring-dapr_app-spring-dapr_1 ... done
```

コンテナを確認します。

```sh
$ docker ps | grep hello-spring-dapr
865c8eeecc80   daprio/daprd:edge       "./daprd --app-id ap…"   42 seconds ago   Up 41 seconds                                                         hello-spring-dapr_app-spring-dapr_1
5c42585aecb3   app-hello-spring-boot   "java -jar app.jar"       43 seconds ago   Up 42 seconds   0.0.0.0:3500->3500/tcp, :::3500->3500/tcp, 8080/tcp   hello-spring-dapr_app-spring_1
d7fd66f7c573   redis:alpine            "docker-entrypoint.s…"   44 seconds ago   Up 42 seconds   0.0.0.0:6380->6379/tcp, :::6380->6379/tcp             hello-spring-dapr_redis_1
40233d3f74db   daprio/dapr             "./placement -port 5…"   44 seconds ago   Up 42 seconds   0.0.0.0:50006->50006/tcp, :::50006->50006/tcp         hello-spring-dapr_placement_1
```

#### Dapr API から Spring Boot アプリにアクセスする

別ターミナルからリクエストします。 

:::note info
Spring Boot アプリの **api/data** エンドポイントを呼び出しています。  
:::

```sh
$ curl http://localhost:3500/v1.0/invoke/app-hello-spring/method/api/data -w '\n'
```

出力

```
{"message":"Hello World!"}
```

Dapr API から "Hello World!" が取得出来ました。  

:::note info
ここまでの手順で、Dapr を Spring Boot アプリの**サイドカー**として設定してコンテナ起動し、 Dapr API から JSON データを取得することが出来ました。
:::

## まとめ

+ Dapr を含め、コンテナ起動した Spring Boot アプリの REST API を Dapr API 経由で呼び出すことが出来ました。
+ この記事の例ではまだ Spring Boot 側のアプリに Dapr への依存関係はありません。
+ 今後さらに Spring Boot から Dapr クライアントオブジェクトを操作する方法を学ぶ必要があります。

どうでしたか？ WSL Ubuntu で Dapr ランタイムを使用した開発環境が手軽に構築できます。ぜひお試しください。今後も Ubuntu の開発環境などを紹介していきますので、ぜひお楽しみにしてください。

## 推奨コンテンツ

https://qiita.com/studio_meowtoon/items/0d28fc54b395520d880b

## 参考資料

+ [Dapr SDK Java](https://docs.dapr.io/developing-applications/sdks/java/)