0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Dapr と Express と Spring Boot でマイクロサービスを構成する:Azure 編

Last updated at Posted at 2023-07-28

Dapr と Express と Spring Boot でマイクロサービスを構成する:Azure 編

こんにちは、@studio_meowtoon です。今回は、Azure Container Apps にて、Dapr と Express と Spring Boot を利用してマイクロサービスを構成する方法を紹介します。
dapr_on_azure-container-apps.png

目的

分散アプリケーションの為のランタイム Dapr の理解を深めます。

実現すること

Microsoft Azure Container Apps 環境にて、Dapr、Express、Spring Boot で構成する、シンプルなマイクロサービスを実装します。

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

開発環境

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

WSL の Ubuntu を操作していきますので macOS の方も参考にして頂けます。

WSL (Microsoft Store アプリ版) ※ こちらの関連記事からインストール方法をご確認いただけます

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

Ubuntu ※ こちらの関連記事からインストール方法をご確認いただけます

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

npm ※ こちらの関連記事からインストール方法をご確認いただけます

$ node -v
v19.8.1
$ npm -v
9.5.1

Java JDK ※ こちらの関連記事からインストール方法をご確認いただけます

$ 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 ※ こちらの関連記事からインストール方法をご確認いただけます

$ 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 ※ こちらの関連記事からインストール方法をご確認いただけます

$ docker --version
Docker version 23.0.1, build a5ee5b1

Dapr ※ こちらの関連記事からインストール方法をご確認いただけます

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

Azure CLI ※ こちらの関連記事からインストール方法をご確認いただけます

$ az --version
azure-cli                         2.45.0
core                              2.45.0
telemetry                          1.0.8

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

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

No エンドポイント HTTPメソッド MIME タイプ
1 /api/data GET application/json
説明を開きます。

/api/data というエンドポイントを実装するバックエンドサービスと、HTTP GET リクエストを送信して、JSON データを取得するフロントエンドのクライアントアプリを実装します。

バックエンドサービスを実装

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

プロジェクトフォルダに移動

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

$ cd ~/tmp/hello-spring-dapr

Java アプリをビルド

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

$ mvn clean package

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

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

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

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

コンテナイメージを Docker Hub にプッシュ

こちらの関連記事で手順がご確認いただけます。

Docker Hub にログインします。

$ docker login
Login Succeeded

コンテナイメージにタグを付けます。

$USER の部分はご自身のコンテナリポジトリに読み替えて下さい。

$ docker tag app-hello-spring-boot $USER/app-hello-spring-boot:latest

Docker Hub にコンテナイメージをプュシュします。

$ docker push $USER/app-hello-spring-boot:latest

ここまでの手順で、Docker Hub に Spring Boot アプリのコンテナイメージを公開することができました。

フロントエンドアプリを実装

Azure Container Apps の構成ではフロントエンドアプリの React コンテナからバックエンドサービスの Spring Boot コンテナに直接 Dapr API を通してアクセスすることはできません。代わりにこの記事ではサーバーサイドで動作する Express を使用してフロントエンドアプリを実装します。

プロジェクトフォルダの作成

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

$ mkdir -p ~/tmp/hello-express
$ cd ~/tmp/hello-express

JS ファイルの作成

server.js JS ファイルを作成します。

$ mkdir -p src
$ vim src/server.js

ファイルの内容

src/server.js
import express from 'express';
import fetch from 'node-fetch';

const app = express();
const port = 3000;

const fetchData = async () => {
    try {
        const response = await fetch('http://localhost:3500/v1.0/invoke/app-hello-spring/method/api/data');
        const data = await response.json();
        return data;
    } catch (error) {
        console.error('データの取得中にエラーが発生しました:', error);
        throw error;
    }
};

app.get('/', async (req, res) => {
    try {
        res.send(`
            <!DOCTYPE html>
            <html>
                <head>
                <title>Hello Express</title>
                </head>
                <body>
                <div id="message"><h2>Loading...</h2></div>
                <button id="fetchButton" onclick="fetchData()">データを取得</button>
                <script>
                    const messageDiv = document.getElementById('message');
                    const fetchButton = document.getElementById('fetchButton');
                    const fetchData = () => {
                    fetch('/api/data')
                        .then(response => response.json())
                        .then(data => {
                        messageDiv.innerHTML = '<h1>' + data.message + '</h1>';
                        fetchButton.style.display = 'none';
                        })
                        .catch(error => {
                        console.error('Error fetching data:', error);
                        });
                    };
                </script>
                </body>
            </html>
        `);
    } catch (error) {
        console.error('エラーが発生しました:', error);
        res.status(500).send('エラーが発生しました');
    }
});

app.get('/api/data', async (req, res) => {
    try {
        const data = await fetchData();
        res.json(data);
    } catch (error) {
        console.error('データの取得中にエラーが発生しました:', error);
        res.status(500).json({ error: 'データの取得中にエラーが発生しました' });
    }
});

app.listen(port, () => {
    console.log(`サーバーは http://localhost:${port} で実行されています`);
});

webpack 設定の作成

webpack.config.js ファイルを作成します。

$ vim webpack.config.js

ファイルの内容

webpack.config.js
const path = require('path');

module.exports = {
  mode: 'development',
  target: 'node',
  entry: './src/server.js',
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'server.bundle.js',
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
          },
        },
      },
    ],
  },
};

プロジェクトの初期化

プロジェクトの初期化を行います。

$ npm init -y

package.json を修正します。

$ vim package.json

ファイルの内容

package.json
{
  "name": "hello-express",
  "version": "1.0.0",
  "description": "",
  "main": "webpack.config.js",
  "scripts": {
    "start": "node build/server.bundle.js",
    "build": "webpack"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

ライブラリをインストールします。

$ npm install express node-fetch --save
$ npm install babel-loader @babel/core @babel/preset-env \
    webpack webpack-cli --save-dev

ローカルでビルド・実行してエラーが出ないか確認します。

$ npm run build
$ npm start

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

Dockerfile を作成します。

$ vim Dockerfile

ファイルの内容

Dockerfile
FROM node:lts-alpine as build-env

WORKDIR /app

COPY package.json package-lock.json /app/
COPY src /app/src
COPY webpack.config.js /app/

RUN npm install
RUN npm run build

FROM node:lts-alpine

WORKDIR /app

COPY --from=build-env /app/build /app/build

RUN npm install express

EXPOSE 3000

CMD ["node", "build/server.bundle.js"]

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

$ docker build -t app-hello-express .

コンテナイメージを確認します。

$ docker images | grep app-hello-express
app-hello-express                 latest    58d8acb77435   21 minutes ago   184MB

コンテナイメージを Docker Hub にプッシュ

コンテナイメージにタグを付けます。

$USER の部分はご自身のコンテナリポジトリに読み替えて下さい。

$ docker tag app-hello-express $USER/app-hello-express:latest

Docker Hub にコンテナイメージをプュシュします。

$ docker push $USER/app-hello-express:latest

ここまでの手順で、Docker Hub に Express アプリのコンテナイメージを公開することができました。

Azure 環境へのデプロイ

シェル変数の作成

シェル変数として、Ubuntu に以下の値を作成します。

location_name=japaneast
resource_group_name=rg-hello
containerapp_env_name=cae-hello

Azure 環境にサインイン

こちらの関連記事からご確認いただけます。

Azure CLI でログインします。

$ az login

Azure 環境の作成

リソースグループ

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

Microsoft.Resources/resourceGroups
$ az group create \
    --name $resource_group_name \
    --location $location_name

コンテナ アプリ環境

コンテナ アプリ環境を作成します。
※ Kubernetes 基盤の環境がベースとなっているので少し時間がかかります。

Microsoft.App/managedEnvironments
$ az containerapp env create \
    --resource-group $resource_group_name \
    --name $containerapp_env_name \
    --location $location_name

Azure Portal での表示
image.png

ここまでの手順で、Azure に Container Apps 環境を作成することができました。

バックエンドサービスをデプロイ

プロジェクトフォルダに移動

プロジェクトフォルダに移動します。

$ cd ~/tmp/hello-spring-dapr

シェル変数の作成

シェル変数として、Ubuntu に以下の値を作成します。状況により、コンテナ アプリの名前を変える必要があります。

resource_group_name=rg-hello
containerapp_env_name=cae-hello
containerapp_name=ca-hello-spring-boot
container_image_name=app-hello-spring-boot:latest

コンテナ アプリ

コンテナ アプリの作成とデプロイを行います。

Microsoft.App/containerApps
$ az containerapp create \
    --resource-group $resource_group_name \
    --environment $containerapp_env_name \
    --name $containerapp_name \
    --image $USER/$container_image_name \
    --target-port 8080 \
    --ingress 'external' \
    --min-replicas 1 \
    --enable-dapr true \
    --dapr-app-id app-hello-spring \
    --dapr-app-port 8080 \
    --dapr-app-protocol http

Azure Portal での表示
image.png
image.png

コンテナに接続

バックエンドサービスの Dapr が有効になっているか確認します。

Container Apps のデフォルト構成では、Dapar API はクラウド環境の外部に公開されていません。

コンテナ アプリに接続します。

$ az containerapp exec \
    --resource-group $resource_group_name \
    --name $containerapp_name

コンテナ アプリに curl をインストールします。
※ コンテナから出るときは ctrl + D を押します。

# apk update
# apk add curl
# curl --version
curl 8.0.1 (x86_64-alpine-linux-musl) libcurl/8.0.1 OpenSSL/1.1.1k zlib/1.2.11 brotli/1.0.9 nghttp2/1.43.0

コンテナ アプリから Dapr API をリクエストして確認します。

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

出力

{"message":"Hello World!"}

ここまでの手順で、Container Apps に、Dapr サイドカーを有効にしたバックエンドサービスをデプロイすることができました。

フロントエンドアプリをデプロイ

プロジェクトフォルダに移動

プロジェクトフォルダに移動します。

$ cd ~/tmp/hello-express

シェル変数の作成

シェル変数として、Ubuntu に以下の値を作成します。状況により、コンテナ アプリの名前を変える必要があります。

resource_group_name=rg-hello
containerapp_env_name=cae-hello
containerapp_name=ca-hello-express
container_image_name=app-hello-express:latest

コンテナ アプリ

コンテナ アプリの作成とデプロイを行います。

Microsoft.App/containerApps
$ az containerapp create \
    --resource-group $resource_group_name \
    --environment $containerapp_env_name \
    --name $containerapp_name \
    --image $USER/$container_image_name \
    --target-port 3000 \
    --ingress 'external' \
    --min-replicas 1 \
    --enable-dapr true \
    --dapr-app-protocol http

Container Apps で構成する場合、フロントエンドアプリのコンテナでも Dapr サイドカーの設定が必須です。

コンテナ アプリを削除する場合は以下のコマンドを実行します。

$ az containerapp delete \
    --resource-group $resource_group_name \
    --name $containerapp_name

Azure Portal での表示
image.png
image.png

コンテナ動作の確認

コンテナ アプリの FQDN を Ubuntu のシェル変数 containerapp_fqdn に取得します。

$ containerapp_fqdn=$(az containerapp show \
    --resource-group $resource_group_name \
    --name $containerapp_name \
    --query 'properties.configuration.ingress.fqdn' \
    --output tsv)

コマンドから Web ブラウザを立ち上げます。

$ sudo apt update
$ sudo apt install wslu
$ wslview https://$containerapp_fqdn/

フロントエンドアプリからバックエンドサービスのデータを取得します。
image.png
image.png

ここまでの手順で、フロントエンドアプリ、バックエンドサービスのそれぞれの Dapr サイドカーを通して連携動作させることができました。

まとめ

  • Dapr、Express、Spring Boot で構成する、シンプルなマイクロサービスを実装することが出来ました。
  • この記事の例ではまだ Spring Boot 側のアプリに Dapr への依存関係はありません。
  • 今後さらに Spring Boot から Dapr クライアントオブジェクトを操作する方法を学ぶ必要があります。

どうでしたか? WSL Ubuntu で Dapr を使用したマイクロサービス開発環境が手軽に構築できます。ぜひお試しください。今後も Ubuntu の開発環境などを紹介していきますので、ぜひお楽しみにしてください。

参考資料

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?