Azure Spring Apps (ASA) に Spring Boot Webサービスをデプロイする (JAR ファイル形式)

# Azure Spring Apps (ASA) に Spring Boot Webサービスをデプロイする (JAR ファイル形式)

こんにちは、@studio_meowtoon です。今回は、Azure Spring Apps 環境で Spring Boot Web アプリケーションを起動する方法を紹介します。
![spring-boot_on_azure-spring-apps.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3206449/b3cd58d0-ff9a-b939-fad7-1a24b479aec3.png)

## 目的

Windows 11 の Linux でクラウド開発します。

こちらから記事の一覧がご覧いただけます。

https://qiita.com/studio_meowtoon/items/6119ab05d8b13527efd8

## 実現すること

Microsoft Azure Spring Apps に、JAR ファイル形式の Spring Boot Web アプリケーションをデプロイします。  

## 技術トピック

### Microsoft Azure Spring Apps とは？  

<details>
<summary>こちらを展開してご覧いただけます。</summary>

### [Microsoft Azure Spring Apps](https://learn.microsoft.com/ja-jp/azure/spring-apps/overview)

:::note info
Microsoft Azure Spring Apps は、Spring Framework で構築されたアプリケーションを Azure 上で実行するためのサービスです。

|特徴とメリット|
|:--|
|オープンソースであり、Spring Boot、Spring Cloud、Spring Cloud Data Flow などの Spring フレームワークをサポートしています。|
|アプリケーションのデプロイやスケーリング、モニタリング、ログ収集などの管理を自動化しています。|
|アプリケーションをコンテナにパッケージ化し、Kubernetes 上で実行することができるます。|
|Azure Active Directory や Azure Key Vault などの Azure サービスとの統合をサポートしています。|
|サービスの管理が自動化されているため、アプリケーションの開発者はインフラストラクチャの管理に時間を費やすことがなくなります。|
|Azure 上でアプリケーションを実行することで、高い可用性やスケーラビリティを実現できます。|
|Azure サービスとの統合が簡単にできるため、セキュリティやアイデンティティの管理が簡単になります。|
|コンテナ化されたアプリケーションは、開発から本番環境まで同じ環境で実行できるため、開発と運用のスピードを向上できます。|
:::

</details>

## 開発環境

+ 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
```

</details>

:::note warn
この記事では基本的に **Ubuntu のターミナルで操作**を行います。**Vim を使用してコピペする方法**を初めて学ぶ人のために、以下の記事で手順を紹介しています。ぜひ挑戦してみてください。
:::

https://qiita.com/studio_meowtoon/items/7771ad48676926e41463

## Hello World を表示する手順 

### Spring Boot Web サービスの作成  

こちらの関連記事の続きから手順を説明する記事となります。

https://qiita.com/studio_meowtoon/items/37ac0082a3228e4de570

### Spring Boot アプリのプロジェクトフォルダに移動

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

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

### Spring Boot アプリをビルド

Java アプリをビルドします。
※ target/app.jar が作成されます。  

```sh
$ mvn clean package
```

### Azure 環境にサインイン

こちらの関連記事の続きから手順を説明する記事となります。 

https://qiita.com/studio_meowtoon/items/9721041f9e6e3e987cf0

Azure CLI でログインします。  

```sh
$ az login
```

### Azure 環境

#### リソースグループ

リソースグループを作成します。

```sh:Microsoft.Resources/resourceGroups
$ az group create \
    --name rg-hello \
    --location japaneast
```

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

:::note info
このコマンドは、Azure CLI を使用して Azure のリソースグループを作成しています。

|コマンド|内容|
|:--|:--|
|az group create|Azure のリソースグループを作成するためのコマンドです。|

|オプション|値|内容|
|:--|:--|:--|
|--name|rg-hello|リソースグループの名前を指定します。|
|--location|japaneast|リソースグループを作成する場所を **japaneast** に指定しています。 **japaneast** は Azure の日本東部地域を指します。|
:::

</details>

#### Spring Apps サービスインインスタンス

拡張機能をインストールします。  
※ 初回のみ必要となります。  

<details>
<summary>手順を表示します。</summary>

##### 拡張機能

拡張機能をインストールします。  

```sh
$ az extension add --name spring
```

:::note warn
拡張機能の一覧を表示する場合は以下のコマンドです。
:::

```sh
$ az extension list
```

</details>

Spring Apps サービスインスタンスを作成します。
※ Kubernetes 基盤の環境がベースとなっているので少し時間がかかります。  

:::note alert
--sku Free では作成できません。 
:::

```sh:Microsoft.AppPlatform/Spring
$ az spring create \
    --resource-group rg-hello \
    --name aps-hello \
    --location japaneast \
    --sku Basic
```

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

:::note info
このコマンドは、Spring Apps サービスインスタンスを作成しています。

|コマンド|内容|
|:--|:--|
|az spring create|Spring Apps サービスインスタンスを作成するためのコマンドです。|

|オプション|値|内容|
|:--|:--|:--|
|--resource-group|rg-hello|Spring Apps サービスインスタンスを作成するリソースグループの名前を指定します。|
|--name|aps-hello|Spring Apps サービスインスタンスの名前を指定します。|
|--location|japaneast|Spring Apps サービスインスタンスを作成する場所を **japaneast** に指定しています。 **japaneast** は Azure の日本東部地域を指します。|
|--sku|Basic|Spring Apps サービスインスタンスのサービスレベルを指定します。この場合、Basic プランを選択しています。|
:::

</details>

Spring Apps サービスインスタンスを一覧表示してみます。  

```sh
$ az spring list
```

:::note warn
Spring Apps サービスインスタンスを削除する場合は以下のコマンドです。 
※ Yes / No の確認がなく、即時に実行されます。
:::

```sh
$ az spring delete -n <service> -g <group>
```

#### Spring Apps アプリ

Spring Apps アプリの作成を行います。 

```sh:Microsoft.AppPlatform/Spring/apps
$ az spring app create \
    --resource-group rg-hello \
    --service aps-hello \
    --name sap-hello-spring-boot \
    --runtime-version Java_11 \
    --assign-endpoint true
```

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

:::note info
このコマンドは、Spring Apps アプリを作成しています。

|コマンド|内容|
|:--|:--|
|az spring app create|Spring Apps アプリを作成するためのコマンドです。|

|オプション|値|内容|
|:--|:--|:--|
|--resource-group|rg-hello|Spring Apps アプリを作成するリソースグループの名前を指定します。|
|--service|aps-hello|Spring Apps アプリを作成する、Spring Apps サービスインスタンスの名前を指定します。|
|--name|sap-hello-spring-boot|Spring Apps アプリの名前を指定します。|
|--runtime-version|Java_11|Spring Apps アプリを Java 11 ランタイムで実行するように設定します。|
|--assign-endpoint|true|true の場合は直接アクセス用のエンドポイント URL を割り当てます。|
:::

</details>

:::note warn
Spring Apps アプリを一覧表示する場合のコマンドは以下です。
:::

```sh
$ az spring app list -s <service> -g <group>
```

:::note warn
Spring Apps アプリを削除する場合は以下のコマンドです。
※ Yes / No の確認がなく、即時に実行されます。
:::

```sh
$ az spring app delete -n <name> -s <service> -g <group>
```

Spring Apps アプリをデプロイします。

```sh:Microsoft.AppPlatform/Spring/apps/deployments
$ az spring app deploy \
    --resource-group rg-hello \
    --service aps-hello \
    --name sap-hello-spring-boot \
    --artifact-path target/app.jar
```

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

:::note info
このコマンドは、Spring Apps アプリをデプロイしています。

|コマンド|内容|
|:--|:--|
|az spring app deploy|Spring Apps アプリをデプロイするためのコマンドです。|

|オプション|値|内容|
|:--|:--|:--|
|--resource-group|rg-hello|Spring Apps アプリを作成するリソースグループの名前を指定します。|
|--service|aps-hello|Spring Apps アプリを作成する、Spring Apps サービスインスタンスの名前を指定します。|
|--name|sap-hello-spring-boot|Spring Apps アプリの名前を指定します。|
|--artifact-path|target/app.jar|Spring Apps アプリにデプロイするコードの場所を指定します。|
:::

</details>

### Web アプリ動作の確認

デプロイ成功後、以下のURLでアクセス可能です。

```sh
https://<service-name>-<app-name>.azuremicroservices.io
```

:::note warn
表示されたページのエンドポイント "/" には、今回準備したサンプルアプリではコンテンツを設定していません。
:::

WEBブラウザには以下のように表示されます。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3206449/816fe3e4-eceb-0b3d-e63e-1acbc1d3c44c.png)
改めてWEBブラウザで確認します。    
※ URLは環境で読み替えて下さい。  

```sh
https://aps-hello-sap-hello-spring-boot.awesomemicroservices.io/api/data
```

WEBブラウザに {"message":"Hello World!"} と表示され、JSON データを取得することが出来ました。  

※ 別ターミナルから curl コマンドで確認してみます。  

```
$ curl -v https://aps-hello-sap-hello-spring-boot.awesomemicroservices.io/api/data
```

<details>
<summary>詳細を表示します。</summary>

```
$ curl -v https://aps-hello-sap-hello-spring-boot.awesomemicroservices.io/api/data
*   Trying xx.xx.xx.xx:443...
* Connected to aps-hello-sap-hello-spring-boot.awesomemicroservices.io (xx.xx.xx.xx) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: C=US; ST=WA; L=Redmond; O=Microsoft Corporation; CN=*.awesomemicroservices.io
*  start date: Dec 24 18:26:47 2022 GMT
*  expire date: Dec 19 18:26:47 2023 GMT
*  subjectAltName: host "aps-hello-sap-hello-spring-boot.awesomemicroservices.io" matched cert's "*.azuremicroservices.io"
*  issuer: C=US; O=Microsoft Corporation; CN=Microsoft Azure TLS Issuing CA 02
*  SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* Using Stream ID: 1 (easy handle 0x55cc7a361e90)
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
> GET /api/data HTTP/2
> Host: aps-hello-sap-hello-spring-boot.awesomemicroservices.io
> user-agent: curl/7.81.0
> accept: */*
>
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
< HTTP/2 200
< date: Sat, 11 Mar 2023 11:49:30 GMT
< content-type: application/json
< strict-transport-security: max-age=15724800; includeSubDomains
<
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Connection #0 to host aps-hello-sap-hello-spring-boot.awesomemicroservices.io left intact
{"message":"Hello World!"}
```

</details>

ターミナルに {"message":"Hello World!"} と表示され、JSON データを取得することが出来ました。  

:::note info 
Azure Spring Apps 自体が SSL/TLS 対応および HTTP/2 プロトコルをサポートしています。
:::

## アプリ インスタンスに接続

ユーザーのオブジェクト ID を取得します。

```sh
$ az ad signed-in-user show \
    --query id -o tsv
XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
```

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

:::note info
このコマンドは、現在ログインしているユーザーの情報を取得します。

|コマンド|内容|
|:--|:--|
|az ad signed-in-user show|Spring Apps アプリをデプロイするためのコマンドです。|

|オプション|値|内容|
|:--|:--|:--|
|--query|id|--query フラグを使用して、オブジェクト ID だけを抽出します。|
|-o|tsv|-o tsv フラグは、出力をタブ区切りの値にフォーマットすることを指定します。|
:::

これで、Azure CLI を使用して、現在ログインしているユーザーのオブジェクト ID を取得できます。

</details>

ユーザーに 'Azure Spring Apps Connect Role' を割り当てます。

```sh
$ az role assignment create \
    --role 'Azure Spring Apps Connect Role' \
    --scope '/subscriptions/oooooooo-oooo-oooo-oooo-oooooooooooo/resourceGroups/rg-hello/providers/Microsoft.AppPlatform/Spring/aps-hello' \
    --assignee XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
```

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

:::note info
このコマンドは、Spring Apps に接続するために必要なアクセス権を持つ Azure AD アプリケーションに、'Azure Spring Apps Connect Role' というロールを割り当てます。

|コマンド|内容|
|:--|:--|
|az role assignment create|Spring Apps アプリ インスタンスの対話型シェルに接続するためのコマンドです。|

|オプション|値|内容|
|:--|:--|:--|
|--role|'Azure Spring Apps Connect Role'|割り当てるロールの名前を指定しています。|
|--scope|'/subscriptions/oooooooo-oooo-oooo-oooo-oooooooooooo/resourceGroups/rg-hello/providers/Microsoft.AppPlatform/Spring/aps-hello'|ロールの割り当て先となる Spring Apps インスタンスのリソース ID を指定しています。|
|--assignee|XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX|ロールを割り当てる対象のアプリケーションのオブジェクト ID を指定しています。|
:::

</details>

アプリ インスタンスに接続します。

```sh
$ az spring app connect \
    --resource-group rg-hello \
    --service aps-hello \
    --name sap-hello-spring-boot
```

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

:::note info
このコマンドは、Spring Apps アプリ インスタンスの対話型シェル接続します。

|コマンド|内容|
|:--|:--|
|az spring app connect|Spring Apps アプリ インスタンスの対話型シェルに接続するためのコマンドです。|

|オプション|値|内容|
|:--|:--|:--|
|--resource-group|rg-hello|Spring Apps アプリを作成するリソースグループの名前を指定します。|
|--service|aps-hello|Spring Apps アプリを作成する、Spring Apps サービスインスタンスの名前を指定します。|
|--name|sap-hello-spring-boot|Spring Apps アプリの名前を指定します。|
:::

</details>

アプリ インスタンスに接続後にディレクトリを確認します。 
※ アプリ インスタンスから出るときは ctrl + D を押します。  

```
$ pwd
/home/cnb
$ ls -la
total 16
drwxr-xr-x 1 cnb  cnb  4096 Mar 11 09:39 .
drwxr-xr-x 1 root root 4096 Jan  4 03:53 ..
drwxr-xr-x 3 cnb  cnb  4096 Mar 11 09:39 .cache
```

アプリ インスタンスの情報を表示してみます。

```
$ cat /etc/*-release
DISTRIB_ID="Mariner"
DISTRIB_RELEASE="2.0.20221222"
DISTRIB_CODENAME=Mariner
DISTRIB_DESCRIPTION="CBL-Mariner 2.0.20221222"
CBL-Mariner 2.0.20221222
MARINER_BUILD_NUMBER=f08ee5a
NAME="Common Base Linux Mariner"
VERSION="2.0.20221222"
ID=mariner
VERSION_ID="2.0"
PRETTY_NAME="CBL-Mariner/Linux"
ANSI_COLOR="1;34"
HOME_URL="https://aka.ms/cbl-mariner"
BUG_REPORT_URL="https://aka.ms/cbl-mariner"
SUPPORT_URL="https://aka.ms/cbl-mariner"
```
こちらは、ターミナルで top 表示した画像になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3206449/7364f2cd-6f6f-2279-1dda-4e7e3c86179a.png)

:::note warn
この Azure Spring Apps アプリは CBL-Mariner Linux をベースに作成されていることが確認できました。
:::

## Azure Portal
Azure Portal の Azure Spring Apps アプリのコンソールの項目からも確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3206449/1d8e6f1b-8a0e-f72b-aa96-1bb5e80a7cab.png)

## まとめ

Azure Spring Apps 環境で、JAR ファイル形式の Spring Boot Web サービスを起動することができました。

:::note warn
**Maven**、**Azure CLI** を使って、Spring Boot アプリの開発から、Azure 環境へのデプロイまで、**すべてをターミナルから行うことができます**。このように、クラウドでのシステム開発に必要なスキルや理解を深めることができます。初めての人でも簡単に手順を追うことができるので、ぜひ挑戦してみてください。
:::

どうでしたか？ 検証目的として、WSL Ubuntu で、Spring Boot Web アプリケーションを Azure Spring Apps 環境で手軽に起動することができます。ぜひお試しください。今後も Azure の開発環境などを紹介していきますので、ぜひお楽しみにしてください。

## 推奨コンテンツ

https://qiita.com/studio_meowtoon/items/cbcfe1433885bae514db