Azure Web AppsからAzure SQL Databaseに接続して値を表示したい

表題の通り、勉強していこうと思います。

## やりたいこと

## 手順

### ステップ1. Azure上にDBを作成し、ローカルアプリから接続

1. Azure SQL Databaseを作成
1. Azure SQL Databaseにダミーデータを作成
1. ローカル環境でアプリを作成
1. githubにpush

### ステップ2. ローカルのアプリをAzure Web Appにデプロイし、接続

1. Azure Web Appを作成
1. Azure Web Appの環境変数に接続文字列を設定
1. Azure Web Appから接続文字列を読み取ってアクセス

ChatGPTさんにやりたいことを言ったら手順を返してくれました。o1優秀です。

### ステップ1-1. Azure SQL Databaseを作成

https://learn.microsoft.com/ja-jp/azure/azure-sql/database/single-database-create-quickstart?view=azuresql&tabs=azure-portal

手順通りに作成。最近Free TierでSQL Database作成できるようになったのでこれを利用。注意点として、接続を許可するソースに

- Azureリソース
- 作業中のPCのIPアドレス

を追加する事。もちろん、接続文字列を知らなければデータベースに接続はできないが、マナーとして。

なお、もっとセキュアにするならプライベートエンドポイントを作成し、それを指定する方法があるようです。

https://zenn.dev/ibaraki/articles/2dca271069c851

### ステップ1-2. Azure SQL Databaseにダミーデータを作成

Azrue SQL Databaseにクエリエディターという機能があるので、そこからSQL文を発行できます。

適当に追加します。

```sql
CREATE TABLE DataPoints (
    ID INT IDENTITY(1,1) PRIMARY KEY,
    Value INT NOT NULL
);
```

```sql
INSERT INTO DataPoints (Value) VALUES (10), (20), (40), (70);
```

```sql
SELECT * FROM DataPoints;
```

### ステップ1-3. ローカルにアプリを作成

ChatGPTさん任せです。

```index.js
// 必要なモジュールをインポート
const express = require("express");
const sql = require("mssql");
require('dotenv').config();

// Expressアプリケーションを作成
const app = express();

// SQL Server接続設定
const config = {
    user: process.env.DB_USER,
    password: process.env.DB_PASSWORD,
    server: process.env.DB_SERVER,
    database: process.env.DB_NAME,
    options: {
      encrypt: true,
      trustServerCertificate: false
    },
    requestTimeout: 30000
};

// ルートエンドポイントでデータを取得して表示
app.get("/", async (req, res) => {
  try {
    // データベースに接続
    let pool = await sql.connect(config);
    console.log("データベースに接続しました");

    // データをクエリ
    let result = await pool.request().query("SELECT * FROM DataPoints");

    // 結果をブラウザに表示
    res.send(result.recordset);
  } catch (err) {
    console.error("エラーが発生しました", err);
    res.status(500).send("エラーが発生しました: " + err.message);
  }
});

// ポート設定
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`アプリケーションがポート ${PORT} で動作中です`);
});

```

ポイントは以下

- ExpressでWebサーバーを実装
    - 非常に簡単にWebサーバーを実装できます
    - [Express.js完全入門 #JavaScript - Qiita](https://qiita.com/ryome/items/16659012ed8aa0aa1fac)
- DBへの接続文字列は環境変数を設定
    - user: process.env.DB_USER などと書いてある部分にDBのユーザー名、パスワード、サーバー名、データベース名を入力する必要があります
    - 直書きすると危険なため、環境変数ファイルを別で管理します
        - 危険な理由：githubなどにデプロイした時に漏れる可能性、コードを開いたときに人に見られる可能性
        - テストのために、一時的にローカルで直書きするのはあり
- 環境変数は.envファイルに記載し、require('dotenv').config(); で読み込み

こんな感じでDBの文字列が見えれば成功

※ 「2. Azure SQL Databaseにダミーデータを作成」で入れたデータと別のデータの画面ショットになりますが、気にしないでください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147841/21fe4b82-c1c4-8b99-c3eb-ee54231d128f.png)

### ステップ1-4. githubにプッシュ

後続のAzure Web Appへのデプロイのため、githubにプッシュします。ポイントは以下

- .gitignoreファイルを作成し、.env(とnode_modules)を記載
    - .envファイルに接続文字列が記載されているので、これをリポジトリに追加しないようにする
    - githubのリポジトリはプライベート設定なので通常他人に読まれることはないが、万が一の設定ミスなどに備えるし、何よりマナー

### ステップ2-1. Azure Web Appを作成

https://learn.microsoft.com/ja-jp/azure/app-service/quickstart-nodejs?tabs=windows&pivots=development-environment-azure-portal

ここらへんを見ながら作業します。ポイントは以下。

- Free Tierを選択する
- デプロイ元にgithubリポジトリを指定する

デプロイ元にgithubリポジトリを指定すると、github Actionsによってリポジトリの内容がAzure Web Appにプッシュされます。このログはgithub側のActionsタブと、Azure Web App側のデプロイセンターで確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147841/503067c2-5c56-e2a4-bec6-127cd91cc35a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147841/fa383794-0d20-8b73-3b81-93246e526855.png)

ちなみに選択するのはFree Tierですが、Free TierだとなぜかAzure Web Appデプロイ時にgithubソースが選択できず、Basic以上を選択しなければならない…と思いがちですが、Azure Web Appデプロイ後にgithubを選択することで設定できます。

### ステップ2-2. Azure Web Appの環境変数に接続文字列を設定

ポイントは以下。

- 環境変数に.envに設定した文字列を設定する
    - .envファイルはリポジトリに含めないため、Azure Web Appはデータベースへの接続情報を知りません。よって、Azure Web App独自の設定として、環境変数の機能を利用して設定します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147841/a31012e2-c4cc-56a2-32ad-ec9e0c7868b0.png)

ローカル環境では.envファイル、Azure Web Appは環境変数を使う感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147841/f0a8057d-646e-1ef2-de08-4fb1ea1d2ae4.png)

### ステップ2-3. Azure Web Appから接続文字列を読み取ってアクセス

あとはAzure Web AppにURLでアクセスすれば、localhost:3000で表示したものと同じものが表示されるはずです。

----

## 余談：Azure Static Web Appについて

Azure Web Appでググると以下の記事が出てたので、調べてみました。

https://learn.microsoft.com/ja-jp/azure/static-web-apps/database-overview

チュートリアルはこちら。

https://learn.microsoft.com/ja-jp/azure/static-web-apps/database-azure-sql?tabs=bash&pivots=static-web-apps-rest


### Azure Static Web AppとAzure Web Appの違い

- [Azure App Service に Static Web Apps が登場！ | PaaSがかりの部屋](https://k-miyake.github.io/blog/appservice-static-webapps/)
- [Azure Static Web Appsとは？サービスの特徴や静的Webアプリで利用するメリットを解説 – ジード](https://www.zead.co.jp/column/azure-static-web-apps/)

|*サービス*|*Static Web Apps*|*App Service*|
|---|---|---|
|運用コスト|	◎|	○|
|対象Webアプリ|	静的|	静的、動的|
|リージョン|	分散|	1ヵ所|

のようです。

使っていないので分かりませんが、仮に静的アプリをデプロイするならStatic Web Appsがよさそうです。ただ、

- 今回の勉強がどのような方向に進むか分からない事
- 普通のWeb Appの方がナレッジが多そうな事
- 勉強用でFree TierまたはBasic Tierで運用するので、運用コストは低く抑えられること

より普通のWeb Appで進めました。

----

### 余談：Static Web Appを作成する

途中までやったのでログとして残します。

#### 演習をやってみたその1(失敗)

https://learn.microsoft.com/ja-jp/training/paths/azure-static-web-apps/?source=recommendations

Microsoft LearnにAzure Static Web Appを作成するトレーニングがあったのでこれで勉強しようと思ったが、Reactはリポジトリが古いらしくエラーになる。よってこれを中止

#### 演習をやってみたその2(成功)

以下のlearnを見つけ、Vanillaでやってみる。

https://learn.microsoft.com/ja-jp/azure/static-web-apps/getting-started?tabs=vanilla-javascript

このlearn、VSCodeからのデプロイや、Azure Portalからのデプロイなど対応しており、フレームワークもReactや素のWebサイトから選べるので対応範囲が広くてはじめやすいと思います。

### SQL Databaseを作成する

以下を実施

https://learn.microsoft.com/ja-jp/azure/azure-sql/database/single-database-create-quickstart?view=azuresql&tabs=azure-portal

### 素のStatic Web AppsとSQL Databaseが出来たので、learnに戻る

ここから再開します。

[データベース接続を構成する](https://learn.microsoft.com/ja-jp/azure/static-web-apps/database-azure-sql?tabs=bash&pivots=static-web-apps-rest#configure-database-connectivity)

データベース接続文字列を取得して staticwebapp.database.config.json を作るまではいったのですが、上手く接続できませんでした。

このやり方はクールな感じもしますが、個人用途だと.envや環境変数にデータベース接続文字列を入れるのと比べて実用的なメリットはないと感じました。

ここで中断しています。