Azure Web App で React App のデプロイが反映されない際の解決方法

# Azure Web App へ React アプリをデプロイすると...

Azure Web App へ 自分で開発した React アプリをデプロイした際、デプロイが正常終了しているにも関わらず、Web App のスタートアップ画面から表示が切り替わらない。Azure Web App の再起動や VSCode からのデプロイ等も試したが、画面表示はスタートアップのままである。

<img width="900" alt="image.png (248.4 kB)" src="https://img.esa.io/uploads/production/attachments/3505/2022/03/07/10862/e0e35b5b-ead8-489b-9909-1d9df3eff2c1.png">

# Web App のログを追いかける

**App Service > 監視 > ログストリーム** を開き、Web App の起動ログを確認する。

> <img width="1200" alt="image.png (455.7 kB)" src="https://img.esa.io/uploads/production/attachments/3505/2022/03/07/10862/589c4cb7-1e61-40ef-bffc-f5c3943d9aca.png">
> 
> ↑ Web App ( Linux | Node 16 LTS  ) の場合の表示内容

Microsoft Container Regstry (MCR) から コンテナイメージを Pull して、
``Docker run`` コマンドでコンテナを実行している。

その後、コンテナに含まれているシェルスクリプト ``/opt/startup/startup.sh`` を実行して、``node /opt/startup/default-static-site.js`` コマンドで、Web App 初期ページを表示するための アプリケーションを起動している。

```/opt/startup/startup.sh
#!/bin/sh

# ソースディレクトリへの移動 - ユーザーが期待する場所でスクリプトが実行されることを確認する
cd "/home/site/wwwroot"

# 環境変数を定義する (NODE_PATH)
export NODE_PATH=/usr/local/lib/node_modules:$NODE_PATH

# 環境変数 : $PORT の文字列長 (length) が 0 なら true 判定
# true の場合のみ、環境変数 (PORT) を定義する
if [ -z "$PORT" ]; then
	export PORT=8080
fi

echo Found tar.gz based node_modules.

# 変数をセットする
extractionCommand="tar -xzf node_modules.tar.gz -C /node_modules"
echo "Removing existing modules directory from root..."

# ディレクトリの削除
rm -fr /node_modules

# ディレクトリの新規作成
mkdir -p /node_modules

echo Extracting modules...

# extractionCommand 変数に含まれるコマンドを実行する
# tar -xzf node_modules.tar.gz -C /node_modules
$extractionCommand

# 環境変数をセットする
export NODE_PATH="/node_modules":$NODE_PATH
export PATH=/node_modules/.bin:$PATH

# ディレクトリの移動 : node_modeules がディレクトリなら true
if [ -d node_modules ]; then
    mv -f node_modules _del_node_modules || true
fi

# シンボリックリンクの作成 : node_modules がディレクトリなら true
if [ -d /node_modules ]; then
    ln -sfn /node_modules ./node_modules
fi

echo "Done."

# 環境変数のセット
export NODE_OPTIONS='--require /usr/local/lib/node_modules/applicationinsights/out/Bootstrap/Oryx.js ' $NODE_OPTIONS

# アプリケーションファイルの実行 (node.js)
node /opt/startup/default-static-site.js
```

# SSH で Web App コンテナイメージ内のプロセスを確認する

コンテナ内で実際にどんなプロセスが立ち上がっているのか、確認するため、
実際に Web App が動作しているコンテナへ SSH を行ってみる。

**Azure Portal > 開発ツール > SSH** を開き、Web App へ SSH を選択する。

<img width="600" alt="image.png (154.4 kB)" src="https://img.esa.io/uploads/production/attachments/3505/2022/03/07/10862/2b5b011d-32fd-4ddd-8cfe-b363d34dbf71.png">

実際に、``ps -x`` コマンドを実行してみると..

<img width="600" alt="image.png (263.9 kB)" src="https://img.esa.io/uploads/production/attachments/3505/2022/03/07/10862/49b8c9d0-d3bf-4eeb-a896-1bb90da07d18.png">

``/opt/startup/startup.sh`` シェルスクリプトが実行され、``node /opt/startup/default-static-site.js`` コマンドによるプロセスが立ち上がっていることが確認できた。

# Node.js サーバー起動オプションを調べる
初期ページでなく、デプロイしたアプリケーションを Web App で実行するためには、
スタートアップコマンドを変更する必要があると仮説を立て、ドキュメントを眺めてみる。

Node.js コンテナーでは、サーバーを構成する方法が以下3つ存在する。

| ツール | 目的 |
| --- | --- |
| PM2 で実行する | **推奨** : 運用または、ステージング環境での使用。 |
| npm start を実行する | 開発での使用 |
| カスタムコマンドを実行する | 開発、またはステージング環境で使用  |

Web App には、標準で **PM2** ``(ロードバランサーが組み込まれた Node.js アプリケーションの製品向けプロセスマネージャー)`` が付属しており、一般的な Node.js ファイルがプロジェクト内に存在する場合は、PM2 を使って アプリケーションを自動実行してくれるとの記載があった。

- bin/www
- server.js
- app.js
- index.js
- hostingstart.js
- process.json および ecosystem.config.js

さらにドキュメントを読み進めると、Web App ( Node 14 LTS ) 以降では、PM2 で、アプリケーションを自動起動しないと注意書きがあることに気がつく。

<img width="900" alt="image.png (69.7 kB)" src="https://img.esa.io/uploads/production/attachments/3505/2022/03/07/10862/a113d0c2-0d78-4834-b6c9-6cf1fa1619e0.png">

解決策としては、Web App にスタートアップコマンドの設定を行う必要があるようなので、実際にスタートアップコマンドを設定してみる。

# スタートアップコマンドを設定する

**Web App > 設定 > 構成 > 全般設定** より **スタートアップコマンド** を設定することが可能です。

今回のプロジェクトは、``/home/site/wwwroot/build`` 配下にアプリケーションコードをデプロイしたので、以下のコマンドを設定、保存します。

```
pm2 serve /home/site/wwwroot/build --no-daemon
```

<img width="900" alt="image.png (166.4 kB)" src="https://img.esa.io/uploads/production/attachments/3505/2022/03/07/10862/f204fea9-809d-4e9c-9541-c4296a21e9c0.png">

設定を保存すると、Web App の自動再起動が実施されます。

再起動後、Web ブラウザで再度 Web App (URL) へアクセスすると、
無事デプロイ後の Web アプリケーションを表示することができました！

# おわりに
クイックスタートでは、この設定が不要だったのでかなり詰まってしまいましたが、
無事 Web App へコードをデプロイ、挙動確認することができたので良かったです。

# 参考文献
- [Node.js サーバーを構成する](https://docs.microsoft.com/ja-jp/azure/app-service/configure-language-nodejs?pivots=platform-linux#configure-nodejs-server)
- [React App not starting in azure app service | Stack Overflow](https://stackoverflow.com/questions/56624277/react-app-not-starting-in-azure-app-service)