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

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

## 目的

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

## 実現すること

Ubuntu の Docker 環境でコンテナとして起動した Spring Boot WEBアプリに Dapr API からアクセスするシンプルな例を実装します。  
※ [Spring Boot REST API に Dapr API からアクセスする手順 (基本編)](https://qiita.com/hiroxpepe/items/428b5d1b45ccb397abe7) 記事の続きになります。  

## 開発環境

+ Windows 11 Home 22H2 を使用しています。  
+ [WSL](https://learn.microsoft.com/ja-jp/windows/wsl/about) の Ubuntu を操作していきますので macOS の方も参考にして頂けます。  

<details>

WSL (Microsoft Store アプリ版)

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

Ubuntu

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

Java JDK [※ 最小構成 Java JDK の導入と Hello World!](https://qiita.com/hiroxpepe/items/8650664e466906a57996)

```sh
$ java -version
openjdk version "11.0.17" 2022-10-18
OpenJDK Runtime Environment (build 11.0.17+8-post-Ubuntu-1ubuntu222.04)
OpenJDK 64-Bit Server VM (build 11.0.17+8-post-Ubuntu-1ubuntu222.04, mixed mode, sharing)
```

Maven [※ 最小構成 Maven の導入と Hello World!](https://qiita.com/hiroxpepe/items/40f7f199b9be7f9e3b5b)

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

Docker Desktop

```sh
Version 4.16.3 (96739)
```

```sh
$ docker --version
Docker version 20.10.22, build 3a2c30b
```

```sh
$ docker-compose --version
Docker Compose version v2.15.1
```

Dapr [※ Dapr CLI をインストールする手順](https://qiita.com/hiroxpepe/items/070c6efe6e84c683e336)

```sh
$ dapr --version
CLI version: 1.10.0
Runtime version: 1.10.0
```

</details>

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

## Dapr ランタイムを削除する  
※ これから docker-compose で立ち上げるコンテナ群で Dapr ランタイムが構成されます。  

ランタイムの削除

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

ランタイムの確認

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

※ ランタイムは削除されました。

## "Hello World" を表示する手順

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

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

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

### Java アプリビルド

ビルド  
※ target/app.jar が作成されます。

```sh
$ mvn clean install
```

### Docker イメージビルド

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   10c6cdc26e44   52 seconds ago   278MB
```

app-hello-spring-boot イメージが作成されました。  

### docker-compose.yml の作成

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

ファイルの内容

```yaml
version: '3'
services:
  ############################
  # Spring Boot app
  app-spring:
    image: app-hello-spring-boot
    depends_on:
      - redis
      - placement
    ports:
      - "3500:3500"
    networks:
      - hello-dapr
  ############################
  # Dapr sidecar
  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:
      - hello-dapr
  ############################
  # Redis state store
  redis:
    image: redis:alpine
    ports:
      - "6380:6379"
    networks:
      - hello-dapr
networks:
    hello-dapr:
```

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

### Docker 環境で起動

コンテナ起動

```sh
$ docker-compose up -d
[+] Running 5/5
 ⠿ Network hello-spring-dapr_hello-dapr           Created
 ⠿ Container hello-spring-dapr-redis-1            Started
 ⠿ Container hello-spring-dapr-placement-1        Started
 ⠿ Container hello-spring-dapr-app-spring-1       Started
 ⠿ Container hello-spring-dapr-app-spring-dapr-1  Started
```

コンテナ確認

```sh
$ docker ps | grep hello-spring-dapr
f78ff3dd48de   daprio/daprd:edge       "./daprd -app-id app…"                                      hello-spring-dapr-app-spring-dapr-1
1bbee3389e16   app-hello-spring-boot   "java -jar app.jar"       0.0.0.0:3500->3500/tcp, 8080/tcp   hello-spring-dapr-app-spring-1
40b98ebf6f15   redis:alpine            "docker-entrypoint.s…"   0.0.0.0:6380->6379/tcp             hello-spring-dapr-redis-1
6b02fc63b165   daprio/dapr             "./placement -port 5…"   0.0.0.0:50006->50006/tcp           hello-spring-dapr-placement-1
```

※ Docker Desktop を確認するとコンテナとして起動しています。  


リクエストして確認

```sh
$ curl -X GET http://localhost:3500/v1.0/invoke/app-hello-spring/method/hello
Hello World!
```

独自にコンテナ起動した Dapr API から "Hello World!" が取得出来ました。  

## まとめ

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

## 公式リファレンス

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