AzureでサーバーレスWebアプリを構築　Javascript版

この記事はAzureのサービスを利用してサーバーレスWebアプリを構築するチュートリアルをJavascript版で行った記録です。
★作成が2018年11月時点であるが、長期保留
★某プロジェクト内研修準備のために、2019年8月25日に復習をかねて修正、公開
※実際の現状より古いかもしれませんので参考程度にとどめ、最新情報をアップされることをお願いいたします。

# A.　目的・動機など
2018年夏、某案件にて、MIcrosoftに相談したところ、「Paasが良いだろう」とのこと。
しかし、Paasは英語でしか情報・サポートが得られない
Paasの案件事例を探すと、富士フィルムの「IMAGEWORKS(イメージワークス)」の件が。
[Microsoft AzureのPaaSを最大限に活用したモダナイゼーションを実施 - 富士フイルムソフトウエア](https://news.mynavi.jp/kikaku/azure_case_td-26/)

要件等が似ているので参考にしてまずはミニチュア版をつくろうかと考える(2018.11．18現在)

で、チュートリアルがあったのでトライする。
[Build a serverless web app in Azure](https://docs.microsoft.com/ja-jp/azure/functions/tutorial-static-website-serverless-api-with-database-old)

プロジェクト進行上の理由および作成途中で下書きのまま放置していたが、研修のため、再開(2019.08．25現在)

# B. 前提条件・注意事項など
「Paasって何？」から開始して。
上記タグのすべて初挑戦。未知識未経験の状態から。

Webシステム構築経験あり(Java、PHPベース、JavascriptはjQueryぐらい？)。
RDBの経験は多いが、NoSQLデータベースはほぼないに等しい。

##　ランタイムのバージョンについて
2018.11.18現在、project.jsonの読み込みに失敗することがあるが、私はランタイムのバージョンをさげて対応した。
[Azure Functionでproject.json のパッケージ読み込みが行わないときは、バージョンが違うかもしれない](https://qiita.com/Quantum/items/fbfc923f9f174e936aae)
##　コンソールは３種類
※入力するコンソールを間違えないようにする。
###　Azure CLI(Bash)
azコマンドによるアカウント作成、DB作成、環境変数設定などを実行する際に使用
![image.png](https://qiita-image-store.s3.amazonaws.com/0/303735/db6d0952-6dce-622a-1d7e-4166783ff51b.png)

###　Function Appのコンソール
functionapp よりプラットフォーム機能をクリック、コンソールを選択
JavaScriptのpackageインストールコマンド(npmなど)を実行
![image.png](https://qiita-image-store.s3.amazonaws.com/0/303735/b8ea8fb9-c81f-21ce-191f-c076009334df.png)


###　Function App　各関数のコンソール
プログラム実行など
![image.png](https://qiita-image-store.s3.amazonaws.com/0/303735/2be72717-5e78-bcad-3a9b-3a94558c79f8.png)


# C. プログラム言語など
C# については
上記の翻訳版がQiita内に
[AzureでサーバーレスWebアプリを構築する【翻訳】](https://qiita.com/akiyoshi-t/items/c7bdaf7e351513e8faca#function-app%E3%81%AEcors%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B)

以下、C#については本家ドキュメント参照とし、記載を省略する。

こちらの記事はJavascript版で作成。
チュートリアルで使われているので、Javascript(vue.js)
実際に必要なときは、画像処理をオンラインでできる処理も必要なため、
Javascriptをベースに考え中。
※機会があれば別記事にて

#　D.　必要なAzureサービス群
１、Blob Storage：静的サイト(HTML,CSS,JS)を配信、画像格納。
２、Azure Functions：機能提供（画像のアップロード、サイズ変更、メタデータの格納）
３、Cosmos DB：画像のメタデータ格納
４、Logic Apps：Computer Vision APIより画像のキャプション取得
５、Azure Active Directory：ユーザー認証
６、そしてAzure services：サーバ提供

#　E. 作業概要／チェックシート
- [ ] １、Azure Blob Storage設定
- [ ] ２、Azure FunctionsにてAzure Blob Storageに画像をアップロード
- [ ] ３、Azure Functionsにて画像をリサイズ
- [ ] ４、画像のメタデータをCosmos DBに格納
- [ ] ５、Cognitive Service Vision APIを使ってキャプションを自動生成
- [ ] ６、Azure Active Directoryにてユーザー認証
- [ ] ７、Azure Blob storageにWebアプリ作成（チュートリアル使用）

#１、Azure Blob Storage設定
ストレージアカウントにはテーブル、キュー、ファイル、BLOB（オブジェクト）、仮想マシンディスクなどを格納できる。

##1-1　リソースグループとは
管理を容易にするために、関連するAzureリソースをまとめるコンテナ 
チュートリアル通りに「first-serverless-app」で新規作成。
locationはjapaneast(東日本)で作成（※locationの違いは影響なし）
※locationについてはこちら

```Bash
Azure CLI(Bash)
azure location list | grep -i location | grep data | awk '{print$2" : "$4}'
```

### 1-1-1　リソースグループを作成

```Bash
Azure CLI(Bash)
 az group create -n first-serverless-app -l japaneast
```

### 1-1-2　Blob StorageのStorageアカウント作成
このチュートリアルの静的コンテンツ（HTML、CSS、およびJavaScriptファイル）を格納する

・ストレージアカウント\<storage account name\>をGlobalで一意な名前で作成
・汎用V2を指定。

```Bash
Azure CLI(Bash)　※Cloud Shellとも
az storage account create -n <storage account name> -g first-serverless-app --kind StorageV2 -l westcentralus --https-only true --sku Standard_LRS
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/303735/5b28f8cb-8cc1-6956-1d50-7095698d899a.png)

### 1-1-3　Blob StorageのStorage設定
1. 作成したストレージアカウントを見つけて開く
　※Azureポータルの上部にある検索バーを使用すると見つけやすい。
2. 左側のナビゲーションで、静的なWebサイト（プレビュー）を選択
3. 静的なWebサイトホスティングのコンテナを設定

- [ ]  有効を選択
- [ ] インデックスドキュメント名にindex.htmlを入力
- [ ] プライマリエンドポイントを保存(作成するWebアプリケーションのURL)

＜例＞　https://\<storage account name\>.z11.web.core.windows.net/

![image.png](https://qiita-image-store.s3.amazonaws.com/0/303735/f5d51e71-a40c-d169-91d5-0f1bf9468c62.png)

### 1-1-4 Webアプリケーションを設定
1．GitHubリポジトリからチュートリアルのリポジトリをクローン

```Bash
Azure CLI(Bash)
cd ~
git clone https://github.com/Azure-Samples/functions-first-serverless-web-application
```

※リポジトリは/home/\<username\>/functions-first-serverless-web-applicationにクローンされる

2．npmコマンドを実行して、アプリケーションの依存関係をインストール、ビルド
※数分時間がかかることもある

```Bash
Azure CLI(Bash)
cd ~/functions-first-serverless-web-application/www
npm install
npm run generate
```

※アプリケーションはdistフォルダに生成される。

3．distへ移動、アプリケーションを$web Blobコンテナーにアップロード

```Bash
Azure CLI(Bash)
cd dist
az storage blob upload-batch -s . -d \$web --account-name <storage account name>
```

4．WebブラウザでStorage静的WebサイトのプライマリエンドポイントURLを開く。


#２、Azure FunctionsにてAzure Blob Storageに画像をアップロード
## 2-1 Azure Function appとは
Azure Functionsは、サーバーレスファンクションを実行するためのサービス
※ファンクション=関数
＜サーバレスファンクションの仕事例＞
・HTTPリクエスト
・BLOBの作成
・イベントのトリガー

Azure Function appは少なくとも１つのサーバーレスファンクションのためのコンテナである

##2-1-1 リソースグループに新しいAzure Function appを作成
一意の名前を持つ新しいAzure Function appを作成
・Function appsにはストレージアカウントが必要
※1-1-2で作成したストレージアカウントを使用

```Bash
Azure CLI(Bash)
az functionapp create -n <function app name> -g first-serverless-app -s <storage account name> -c japaneast
```

##2-2 HTTPリクエストで起動されるサーバーレスファンクションを作成
### 2-2-1　HTTP　Trigger作成
画像をBlobストレージに安全にアップロードする時間制限付きURLでHTTPリクエストするサーバレスファンクションを作成
このファンクションはHTTPリクエストによってトリガーされる
Azure Storage SDKを使用してセキュアなURLを生成して返す

1．Function appをAzureポータルで検索、開く
2．「関数」にフォーカス、+をクリックして新しいサーバーレスファンクションの作成を開始
3．カスタム関数をクリックして、関数テンプレートのリストを表示
4．HTTPTriggerテンプレートを選択
5．以下の値を設定する

| 設定             | 値                |
|:-----------------|:------------------|
| 言語             | JavaScript        |
| 名前             | GetUploadUrl      |
| 承認レベル       | Anonymous         |

![image.png](https://qiita-image-store.s3.amazonaws.com/0/303735/b03ea15e-41f5-46d1-baa0-d779c966ff27.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/303735/0d71330d-2200-1b85-5d06-798546f466ef.png)

### 2-2-2 npmパッケージをインストール
Function Appのコンソールを開く
※現在のディレクトリがd：\ home \ site \ wwwrootであることを確認
空のpackage.jsonファイルを作成

``` Bash
Function Appのコンソール
cd d:\home\site\wwwroot
npm init -y
```

コンソールでコマンドを実行してパッケージをインストール、package.jsonに保存

``` Bash
Function Appのコンソール
npm install --save azure-storage
```

※操作を完了するまでに数分かかる。

### 2-2-3 Javascriptでコードを記載する
1．Function Appのコンソール左側のナビゲーションで関数名（GetUploadUrl）を選択
関数を表示し、index.jsの中を全削除
2．チュートリアルのソースに書き換え
[javascript / GetUploadUrl / index.js](https://raw.githubusercontent.com/Azure-Samples/functions-first-serverless-web-application/master/javascript/GetUploadUrl/index.js)に書き換え

## 2-3　セキュアなURL作成の設定（Shared Access Signature（SAS）URL）
セキュアなURLを構築するために必要な共有アクセス署名（SAS）トークンを生成するための設定を行う

###2-3-1 SAS URLとは
・短期間有効
・1つのファイルのみをアップロードすることができる

###2-3-2 環境変数の追加
ストレージ接続文字列の環境変数を追加する
※ストレージアカウントの接続文字列が必要
アプリケーション設定に保存することができるため、その操作を行う

1. ストレージアカウントの接続文字列を照会し、STORAGE_CONNECTION_STRINGという名前のbash変数に保存

```Bash
Azure CLI(Bash)
export STORAGE_CONNECTION_STRING=$(az storage account show-connection-string -n <storage account name> -g first-serverless-app --query "connectionString" --output tsv)
echo $STORAGE_CONNECTION_STRING
```


2. AZURE_STORAGE_CONNECTION_STRINGという名前の新しいアプリケーション設定を作成

```Bash
Azure CLI(Bash)
az functionapp config appsettings set -n <function app name> -g first-serverless-app --settings AZURE_STORAGE_CONNECTION_STRING=$STORAGE_CONNECTION_STRING -o table
```

※コマンドの出力に正しい値の新しいアプリケーション設定が含まれていることを確認

##2-4 サーバーレスファンクションのテスト
1．テストパネルを展開
2．HTTPメソッドをGetに変更
3．パラメータ設定

| name             | value             |
|:-----------------|:------------------|
| filename         | image1.jpg        |

4．テストパネルの実行
出力にアップロード用URLを返却。ファンクションの実行結果はログパネルに表示。


##2-5　Function AppのCORSを設定
###　2-5-1　CORS（cross-origin resource sharing）設定とは
・アプリのフロントエンドはBLOBストレージでホストされている。
・Azure Function appとは異なるドメイン名を使用している。
・クライアント側のJavaScriptが作成したファンクションを正常に呼び出すためには、CORS用にFunction appに設定する必要がある。

###　2-5-2　CORS設定
1．アプリのURLを設定する(最後の/を省略)

＜例＞　https://\<storage account name\>.z11.web.core.windows.net

![image.png](https://qiita-image-store.s3.amazonaws.com/0/303735/89537752-d7d9-554a-a72c-7030a0a19ac3.png)

2．Function Appの概要タブを選択し、CORSを有効化するために「再開」

##2-6　ストレージアカウントのCORSを設定
Blobストレージへのクライアント側のJavaScript呼び出しによってファイルをアップロードするため、CORSをStorageアカウントも設定する必要あり。

```Bash
Azure CLI(Bash)
az storage cors add --methods OPTIONS PUT --origins '*' --exposed-headers '*' --allowed-headers '*' --services b --account-name <storage account name>
```

## 2-7 Webアプリ修正
Webアプリケーションは、settings.jsという名前のファイルから設定を取得している。

・window.apiBaseUrlをFunction appのURLに設定
・window.blobBaseUrlをAzure Blob StorageエンドポイントのURLに設定

### 2-7-1 Funcion appのURL設定
Funcion appのURLを照会し、FUNCTION_APP_URLへ格納

```Bash
Azure CLI(Bash)
cd ~/functions-first-serverless-web-application/www/dist
export FUNCTION_APP_URL="https://"$(az functionapp show -n <function app name> -g first-serverless-app --query "defaultHostName" --output tsv)
echo $FUNCTION_APP_URL
```

### 2-7-2 settings.jsを作成、基底URIL設定

```Bash
Azure CLI(Bash)
window.apiBaseUrl = 'https://fnapp@lab.GlobalLabInstanceId.azurewebsites.net'
echo "window.apiBaseUrl = '$FUNCTION_APP_URL'" > settings.js
cat settings.js
```

### 2-7-3 settings.jsへBlob Storageの基底URL設定

```Bash
Azure CLI(Bash)
export BLOB_BASE_URL=$(az storage account show -n <storage account name> -g first-serverless-app --query primaryEndpoints.blob -o tsv | sed 's/\/$//')
echo $BLOB_BASE_URL
```

### 2-7-4 settings.jsへAPIコール用の基底URL設定

```Bash
Azure CLI(Bash)
window.blobBaseUrl = 'https://mystorage.blob.core.windows.net'
echo "window.blobBaseUrl = '$BLOB_BASE_URL'" >> settings.js
cat settings.js
```

### 2-7-5 Blobストレージにファイルをアップロード

```Bash
Azure CLI(Bash)
az storage blob upload -c \$web --account-name <storage account name> -f settings.js -n settings.js
```

##2-8 Webアプリケーションのテスト
この時点でBlobストレージに画像をアップロード可能。
※まだ画像を表示負荷。
GetImages関数をにとほど作成⇒エラーになり、Webページは「Analyzing...」の状態で停止しているように見えるが、アップロード正常。

```Bash
Azure CLI(Bash)
az storage blob list --account-name <storage account name> -c images -o table
```
imagesコンテナの全てのファイルを削除

```Bash
az storage blob delete-batch -s images --account-name <storage account name>
```

#３、Azure Functionsにて画像をリサイズ
blobをトリガーとするサーバーレスファンクションを作成する

## 3-1 サムネイル用の Blob Storage コンテナーを作成する
すべての BLOB へのパブリック アクセスを持つストレージ アカウント内に、thumbnails という名前の新しいコンテナーを作成

```Bash
Azure CLI(Bash)
az storage container create -n thumbnails --account-name <storage account name> --public-access blob
```
## 3-2 BLOB によってトリガーされるサーバーレス関数を作成する
### 3-2-1 Azure Portal で関数アプリを開きます。
### 3-2-1 関数テンプレートの一覧を表示
ウィンドウの左側のナビゲーションで、[Functions] にポインターを合わせて + をクリック
新しいサーバーレス関数の作成を開始
クイックスタートページが表示されたら、[カスタム関数] をクリックして、関数テンプレートの一覧を表示
### 3-2-3 BlobTrigger テンプレートを検索、選択
### 3-2-4 以下の値を使用して、サムネイルを作成する関数を作成

| Setting                          | 推奨値             | 説明     　　　　　　　　        |
|:---------------------------|:----------------------------|:---------------------------------|
| Language         | C# または JavaScript        | 使用したい言語を選択。  |
| 関数名の指定         | ResizeImage	|アプリケーションが関数を検出できるように、この名前を正確に表示されているとおりに入力 |
| パス                      | images/{name} | images コンテナーにファイルが格納されると関数が実行されます。 |
| ストレージ アカウント情報 | AZURE_STORAGE_CONNECTION_STRING | 接続文字列を使用して前に作成した環境変数を使用 |

### 3-2-5 [作成] をクリックして、関数を作成
### 3-2-6 関数が作成されたら、[統合] をクリックして、そのトリガー、入力、および出力バインディングを表示
### 3-2-7 [新規出力] をクリックし、新しい出力バインディングを作成
### 3-2-8 [Azure Blob Storage] を選択し、[選択] をクリック
### 3-2-9 以下の値を入力

| 設定    | 推奨値  |説明
|:---------------------------|:----------------------------|:---------------------------------|
| Blobパラメータ名|thumbnail| この名前のパラメータを使用してサムネイルを書き込み|
| 関数の戻り値を使用する|使用しない|
| パス |thumbnails/{name}| サムネイルは、thumbnailsコンテナに書き込み|
| ストレージアカウント接続|AZURE_STORAGE_CONNECTION_STRING |前のステップで作成した接続文字列の環境変数を使用|

### 3-2-10 JavaScriptを選択している場合
 [詳細エディター] をクリックして、バインディングを表す JSON を表示、
blobTrigger バインディングで、binary の値を持つ dataType という名前のプロパティを追加

```JSON
JSON
{
"name": "myBlob",
"type": "blobTrigger",
"direction": "in",
"path": "images/{name}",
"connection": "AZURE_STORAGE_CONNECTION_STRING",
"dataType": "binary"
}
```

### 3-2-11 [保存] をクリックし、新しいバインディングを作成
### 3-2-12 C#を選択している場合 (省略)

### 3-2-13 JavaScriptを選択している場合
１、npm パッケージをインストールする。左側のナビゲーションで関数アプリの名前をクリック、[プラットフォーム機能] をクリック
２、[コンソール] をクリックしてコンソール ウィンドウを表示
３、コンソールで npm install jimp コマンドを実行
４、左側のナビゲーションで関数名 ResizeImage をクリックして関数を表示、index.js のすべてを /javascript/ResizeImage/index.js の内容で置き換え

### 3-2-14 コードウィンドウ下部のログをクリックしてログパネルを展開します。

### 3-2-15 保存をクリックします。ログパネルを見て、ファンクションが正常に保存され、エラーがないことを確認します。

### 3-3 サーバーレスファンクションをテストする
### 3-3-1 ブラウザでアプリケーションを開く
画像ファイルを選択してアップロード
Cloud Shellで、imagesコンテナに画像がアップロードされたか確認
★注意　画像を表示する機能はまだ追加していないため、アップロードした写真はアプリに表示されない

### 3-3-2 images コンテナーに画像がアップロードされていることを確認

```Bash
Azure CLI(Bash)
az storage blob list --account-name <storage account name> -c images -o table
thumbnailsコンテナに画像がアップロードされたか確認します。
```
### 3-3-3 thumbnails いう名前のコンテナー内に、サムネイルが作成されていることを確認

```Bash
Azure CLI(Bash)
az storage blob list --account-name <storage account name> -c thumbnails -o table
```

### 3-3-4 サムネイルのURLを取得

```Bash
Azure CLI(Bash)
az storage blob url --account-name <storage account name> -c thumbnails -n <filename> --output tsv
取得したURLをブラウザで表示して、サムネイルが適切に作成されたことを確認します。
```


### 3-3-5 チュートリアルの次のステップに進む前に、imagesコンテナとthumbnailsコンテナの全てのファイルを削除

```Bash
Azure CLI(Bash)
az storage blob delete-batch -s images --account-name <storage account 
az storage blob delete-batch -s thumbnails --account-name <storage account name>
```


#４、画像のメタデータをCosmos DBに格納
## 4-1 Cosmos DBのアカウント・データベース・コレクションを作成
Cosmos DBアカウントは、Cosmos DBデータベースを含むAzureリソースです。

###4-1-1 Cloud Shell（bash）にサインインを確認
###4-1-2 一意の名前を持つCosmos DBアカウントを作成

```Bash
Azure CLI(Bash)
az cosmosdb create -g first-serverless-app -n <cosmos db account name>
```

###4-1-3 アカウントにimagesdbという名前の新しいデータベースを作成

```Bash
Azure CLI(Bash)
az cosmosdb database create -g first-serverless-app -n <cosmos db account name> --db-name imagesdb
```

###4-1-4 データベースにimagesという名前の新しいコレクションを作成

```Bash
Azure CLI(Bash)
az cosmosdb collection create -g first-serverless-app -n <cosmos db account name> --db-name imagesdb --collection-name images --throughput 400
```

##4-2 サムネイルが作成されたときにドキュメントをCosmos DBに保存
ResizeImageファンクションでCosmos DB出力バインディングを設定し、
保存するドキュメント（オブジェクト）を返すようにファンクションを変更

###4-2-1 Azure ポータルでfunction appを開く
###4-2-2 左側のナビゲーションで、ResizeImageファンクションを展開し、統合を選択します。
###4-2-3 出力の下の新しい出力をクリックします。
###4-2-4 Azure Cosmos DBを選択し、選択をクリックします。 
###4-2-5 以下の値をAzure Cosmos DB出力の各種フィールドを入力します。

|設定|推奨値|説明|
|:--------------------------------------|:--------------------------------------|:--------------------------------------|
|ドキュメントパラメータ名|関数の戻り値を使用する|テキストボックスの値は自動的に$returnに設定されます。|
|データベース名|imagesdb|作成したデータベース名を使用します|
|コレクション名|images|作成したコレクション名を使用します|


###4-2-6 Azure Cosmos DBアカウント接続の横にある新規をクリック
前のステップで作成したCosmos DBアカウントを選択
###4-2-7 保存をクリックしてCosmos DB出力バインディングを作成
###4-2-8 ResizeImageファンクションをクリックしてファンクションを開く

### 4-2-9 C#を選択している場合 (省略)
### 4-2-10 JavaScriptの場合
else 句の context.done() ステートメントを変更、CosmosDB に保存するドキュメントを返すコートを記載

``` Javascript
Javascript
if (error) {
 context.done(error);
} else {
 context.bindings.thumbnail = stream;
 context.done(null, {
     id: context.bindingData.name,
     imgPath: "/images/" + context.bindingData.name,
     thumbnailPath: "/thumbnails/" + context.bindingData.name
 });
}
```

### 4-2-11 コードウィンドウ下部のログをクリックしてログパネルを展開
### 4-2-12 保存をクリック

## 4-3 CosmosDBから画像を一覧表示するファンクションを作成する
Cosmos DBから画像メタデータを取得するためのAPIが必要なため、Cosmos DB入力バインディングを使用してデータベースコレクションを照会するHTTPトリガー関数を作成

## 4-3-1 Function appウィンドウの左側のナビゲーションで、+をクリックして新しいサーバーレスファンクションの作成を開始
### 4-3-2 HttpTriggerテンプレートを選択
### 4-3-3 blobアップロードURLを生成する関数を作成

|設定|推奨値|説明|
|:--------------------------------------|:--------------------------------------|:--------------------------------------|
|言語|C#またはJavaScript|使用したい言語を選択|
|名前|GetImages|アプリケーションがFunctionを検出できるように、この名前を正確に入力します。|
|承認レベル|Anonymous|Functionを一般公開します|


### 4-3-4 統合タブをクリック
### 4-3-5 新規インプットをクリックしてAzure Cosmos DBを選択
### 4-3-6 選択をクリック
### 4-3-7 以下の値を入力

|設定|推奨値|説明|
|:--------------------------------------|:--------------------------------------|:--------------------------------------|
|ドキュメントパラメータ名|documents|関数内のパラメータ名と一致します。|
|データベース名|imagesdb||
|コレクション名|images||
|SQLクエリ|select * from c order by c._ts desc|最新のドキュメントから取得する|

Azure Cosmos DB アカウント接続  既存の接続文字列を選択  
### 4-3-8 保存をクリックしてバインディングを作成
### 4-3-9 C#を選択した場合(省略)

### 4-3-10 JavaScriptの場合
関数の名前をクリックしてコードウィンドウを開き、index.js のすべてを /javascript/GetImages/index.js の内容で置き換え

### 4-3-11 コードウィンドウ下部のログをクリックしてログパネルを展開

### 4-3-12 保存をクリック

### 4-4 アプリケーションをテストする
## 4-4-1 ブラウザでアプリケーションを開き、画像ファイルを選択してアップロード
## 4-4-2 新しい画像のサムネイルがページに表示
## 4-4-3 Azureポータルで、検索ボックスを使用してCosmos DBアカウントを名前で検索し、開く
## 4-4-4 データエクスプローラをクリックして、コレクションとドキュメントを表示
## 4-4-5 imagesdbの下のimagesコレクションを選択
## 4-4-6 アップロードした画像に対応するドキュメントが生成されていることを確認

#５、Cognitive Service Vision APIを使ってキャプションを自動生成
Computer Visionを使用して画像にキャプションを追加
Microsoft Cognitive ServicesのComputer Vision APIを使用、
アップロードされた画像のキャプションを生成、Cosmos DBの画像メタデータでキャプションを保存

##5-1 Computer Visionアカウント作成
リソースグループに一意の名前を持つ種類のComputerVisionという新しいCognitive Servicesアカウントを作成

###5-1-1 Enter focus mode](フォーカス モードにする) を選択、Cloud Shell ウィンドウを開く

###5-1-2 ComputerVision という種類の新しい Cognitive Services アカウントを作成

```Bash
Azure CLI(Bash)
az cognitiveservices account create -g first-serverless-app -n <computer vision account name> --kind ComputerVision --sku F0 -l japaneast
```


##5-2 Computer Vision URLとキーのFunction Appのアプリ設定作成
★Computer Vision APIを呼び出すにはURLとキーが必要

###5-2-1 Computer VisionAPIキーとURLを取得、bash変数に保存

```Bash
Azure CLI(Bash)
export COMP_VISION_KEY=$(az cognitiveservices account keys list -g first-serverless-app -n <computer vision account name> --query key1 --output tsv)
export COMP_VISION_URL=$(az cognitiveservices account show -g first-serverless-app -n <computer vision account name> --query endpoint --output tsv)
```

###5-2-1 Function appにそれぞれCOMP_VISION_KEYとCOMP_VISION_URLという名前のアプリ設定作成

```Bash
Azure CLI(Bash)
az functionapp config appsettings set -n <function app name> -g first-serverless-app --settings COMP_VISION_KEY=$COMP_VISION_KEY COMP_VISION_URL=$COMP_VISION_URL -o table
```

##5-3 ResizeImageファンクションよりComputer Vision API呼び出し
ResizeImageファンクションを変更、アップロードした各画像のキャプションを生成、Cosmos DBに生成したキャプションを保存
Computer Vision APIを呼び出す

###5-3-1 Azureポータルでfunction appを開く

###5-3-2 C#の場合(省略)

###5-3-3 JavaScriptの場合
１、npmのaxios パッケージをインストールする
２、[コンソール] をクリックしてコンソール ウィンドウを表示
３、コンソールで npm install axios コマンドを実行
４、左側のナビゲーションで関数名 (ResizeImage) をクリックして関数を表示、
index.js のすべてを /javascript/ResizeImage/index-module5.js の内容で置き換え

##5-3-4 コードウィンドウ下部のログをクリックしてログパネルを展開

###5-3-5 保存をクリックログパネルを見て、ファンクションが正常に保存され、エラーがないことを確認

##5-4 アプリケーションをテスト
###5-4-1 ブラウザでアプリケーションを開きます。 画像ファイルを選択してアップロード
###5-4-2 新しい画像のサムネイルがページに表示 画像の上にマウスを置くと、Computer Visionによって生成された説明が表示

#６、Azure Active Directoryにてユーザー認証
App App Authenticationを追加、WebアプリケーションのバックエンドAPI保護

##6-1 App Service Authenticationを有効に
###6-1-1 Azureポータルでfunction appを開く
###6-1-2 プラットフォーム機能下の認証/承認を選択
###6-1-3 以下の値を入力

|設定|推奨値|説明|
|:--------------------------------------|:--------------------------------------|:--------------------------------------|
|App Service 認証|On|認証を有効にします|
|要求が認証されない場合の実行アクション|Azure Active Directoryでのログイン|設定済みの認証方法を選択します（下記参照）|
|認証プロバイダー|下記参照|下記参照|
|トークン ストア|On|App Serviceにトークンの格納と管理を許可|
|許可される外部リダイレクト URL|作成したwebアプリケーションのURL|App Serviceがユーザーの認証後にリダイレクトできるURL|


###6-1-4 Azure Active Directoryを選択、設定タブを開く
 1. 管理モードとして簡易を選択して以下の値を入力
 2. OKをクリックしてAzure Active Directoryの設定を保存

|設定|推奨値|説明|
|:--------------------------------------|:--------------------------------------|:--------------------------------------|
|App Service 認証|On|認証を有効にします|
|要求が認証されない場合に実行アクション|Azure Active Directoryでのログイン|設定済みの認証方法を選択します（下記参照）|
|認証プロバイダー|下記参照|下記参照|
|トークン ストア|On|App Serviceにトークンの格納と管理を許可|
|許可される外部リダイレクト URL|作成したwebアプリケーションのURL|App Serviceがユーザーの認証後にリダイレクトできるURL|


###6-1-5 保存をクリック

##6-2 認証を有効にする
###6-2-1 現在のディレクトリがwww/distであることを確認

```Bash
Azure CLI(Bash)
cd ~/functions-first-serverless-web-application/www/dist
```

function appで認証を有効にために、settings.jsに次のコードを追加

```Bash
(settings.js)
window.authEnabled = true
```
###6-2-2 次のコマンドを使用か、Vimなどのコマンドラインエディタを使用して変更を行い、結果を表示

```Bash
Azure CLI(Bash)
echo "window.authEnabled = true" >> settings.js
```

変更されたかを確認

```Bash
Azure CLI(Bash)
cat settings.js
```
###6-2-3 Blobストレージにファイルをアップロード


```Bash
Azure CLI(Bash)
az storage blob upload -c \$web --account-name <storage account name> -f settings.js -n settings.js
```

##6-3 アプリケーションをテスト
###6-3-1 ブラウザでアプリケーションを開いて、Log inをクリックしてログイン
###6-3-2 画像ファイルを選択して、アップロード


#７、Azure Blob storageにWebアプリ作成（チュートリアル使用）
Azureサービスを使用したサーバーレスアプリケーションを作成完了

###7-1 リソースを削除する
全ての作業が終了したら、次のコマンドを使用してチュートリアルで作成されたすべてのリソースを削除できます。

```Bash
Azure CLI(Bash)
az group delete --name first-serverless-app
```

プロンプトが表示されたらyを入力

以上になります。