Azure Functions(関数アプリ)の環境構築メモ

Azure OpenAI Serviceの活用でFunctionsを使うことになったので、いろいろ作る前にFunction作るための環境構築のメモを残す

# 環境
* windwos11 pro
* Visual Studio Code（いくつかの拡張機能含む）
* Azure Functions Core Tools
* Python3.11

## Visual Studio Codeのインストール

https://code.visualstudio.com/download

上記からダウンロードしてインストールするだけ

## Azure Functions Core Toolsのインストール

https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-run-local?tabs=windows%2Cisolated-process%2Cnode-v4%2Cpython-v2%2Chttp-trigger%2Ccontainer-apps&pivots=programming-language-python#install-the-azure-functions-core-tools

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/ef6916c5-cc8d-9dc7-b698-69bd7c230920.png)
64ビットのほうをインストールする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/2d2c9ed7-0987-a8dd-f9b9-5f07ec45f2e9.png)

## Pythonのインストール

https://www.python.org/downloads/windows/

上記からPython 3.11.9 をインストールする。
他で使ってるバージョンに合わせただけなので、ぶっちゃけAzureのFunctionsが対応してるバージョンなら新しいものでも大丈夫。

インストール後、念のため再起動しておく。
※以前パスの読み込みがうまくいかないことがあったので念のため

## VSCodeの拡張機能のPythonをインストールする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/63f6953f-b6aa-50a2-f70c-ee2d7a8271c4.png)

## VSCodeの拡張機能のAzure Functionsをインストールする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/4028ac87-0576-4fd9-99a2-574aae69b401.png)

## VSCodeの拡張機能のAzuriteをインストールする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/2fb7d3ed-a214-4f9d-0780-6a91d7c80e51.png)


# 開発スタート
## Azureポータルからリソースグループを作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/08233a50-2e60-d789-e7ed-4b2351b87dd6.png)
とりあえず入れ物だけ作っておく。名前は適当に。

## Azureにサインインする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/b3bc5fc9-099f-4cce-1b0b-a6d42712197b.png)

## プロジェクトを作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/f76826f4-5c61-3edc-4ed4-973876f32566.png)

適当なフォルダを作って指定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/6b309048-0b5a-a30c-ca72-1f5012a16b6b.png)

Pythonを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/8e8f3df4-778f-95ec-1109-c539a176edab.png)

モデルV2を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/92ca0aa2-cc3d-57e4-340a-ec9d182d6c33.png)

インストールしたPythonのバージョンが出てくるのでそれを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/87e6219c-8377-9173-e83e-c8e90e3c6bf1.png)

HTTP triggerを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/6d3c2c79-d45c-64e7-630f-a565c0289398.png)

関数の名前を適当に決める。（とりあえず、「http_trigger_simple_chat」にしておく）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/3cc55e0d-5547-abf7-812c-c16a015b3216.png)

認証レベルについては「FUNCTION」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/83601e78-02b7-1be5-bbc3-a871184039f4.png)

「Open in current windows」を選択してプロジェクトを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/9dfa0447-0b58-c1f8-0de5-9c5d0bc7d789.png)

function_app.pyに初期テンプレートの関数が実装された雛形の構成が作成されるので、ここから本格的な実装をスタートする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/953af99a-ea98-29f4-4382-5ea900afbcc1.png)

# ローカルで実行する
## エミュレータの実行
F1キーとかからコマンドパレットを呼び出して「Azurite:Start」を実行する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/44bf2883-9da4-2f1b-c3c2-363139f8741a.png)

エディタの下のほうにこんなのが出れてばOk
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/d56511a3-655e-80c8-2932-cee79d0f19e1.png)

## 関数の実行
function_app.pyを開いてる状態でF5キー押して実行する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/02eb7ab3-eff7-6aae-266f-6cc42025bf43.png)

ターミナルで警告が出た場合は「R」か「A」で実行を許可する。この環境は専用に作ったVMなので、「A」で常に実行するようにする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/4b84e066-4997-d15b-7b66-dbcd71143c05.png)

エラーなくいくと、ローカル実行しているFunctionsのエンドポイントが表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/84d2c62e-5099-162a-571d-29899d330d47.png)

左のアクティビティからAzureのアイコンをクリックし、ローカルのワークスペース内の関数を右クリックするとメニューが表示されるので、「Execute Function Now」をクリックして関数を実行する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/4931934a-d88b-cead-4efc-688c8a0fde86.png)

コマンドパレットが表示されるあたりに、HTTPリクエストを投げるときにくっつけて渡す要求本文にセットする値の入力が求められるので、今回はこのままEnterで確定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/502f07c0-1085-41db-ab5c-9ddaaea75b95.png)

関数の実行されると、VSCodeに通知が来る。「Hallo Azure・・・・」というテキストが表示されていれば成功！

あとは、この関数の中身を更新していけばOK

## デバッグを止める
Ctrl+Cキーで実行中のプロセスを止める。ターミナルが戻ればOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/06459621-0bde-0d16-ce5c-2e7eaa9899f2.png)

コマンドパレットから「Azurite:Close」でエミュレータを止める
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/8aefea05-534c-2f1f-856e-60de86ac0c8e.png)

# Azureにデプロイする
## 関数アプリを作成する
左のAzureのアイコンをクリックしリソースの中のFunction Appを右クリックし、「Create Function App in Azure」を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/577982b8-8888-1840-8a5c-3594c2bc60c9.png)

関数のアプリ名を適当に入力してEnter
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/c4fda415-d8a8-989e-9cfc-eebd7c34ab3c.png)

Python3.11を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/ef16fb99-f023-2d05-15d7-50a558da54f6.png)

日本リージョンを選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/c1230ff1-6b24-7f44-b105-df11a7beb9e8.png)

うまくいけばAzureのポータルからも関数のリソースが見える

## ローカルで作った関数をデプロイする

左のAzureのアイコンをクリックし、ローカルのWorkSpaceのところにあるFunctionsのアイコンをクリックするとメニューが表示されるので、「Deploy to Function App...」を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/cf081dfd-e8f8-93f8-8ee6-d4b979ec29f2.png)


デプロイ先として先ほど作成した関数を指定する。警告が出たらDeployを選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/581974bc-f56e-7a0b-3b54-42e1666ba258.png)

ターミナルにSuccessのテキストが出れば完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/92be0361-94b1-e5a7-ef19-6e1d01d2c539.png)

# Azure上にデプロイした関数を実行してみる
とりあえずPostmanを使ってVSCode以外から動作確認してみる

## 関数URLを取得する
Azureのポータルにアクセスし、デプロイした関数リソースにアクセスし、関数URLを取得する。
このとき下記の3種類表示されるはずなので、一番下の関数キーの値をコピーする
* _master (ホスト キー)
* default (ホスト キー)
* default (関数キー)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/6e5e20d0-caa7-7c8f-995c-49f70489685c.png)

Postmanにコピーしたやつを張り付けて、Bodyのところにローカル実行したときの引数をセットして実行する
```
{"name":"Azure"}
```
応答として「Hello Azure...」とテキストが返ってきたら成功！


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/6944d850-04e0-a655-ae8f-fd8f4b3da7e8.png)

# 【おまけ】ちょっとセキュアに
今回作成した関数は、認証レベルをFunctionにしてるので、エンドポイントとなるURLだけでなく、関数キーなどのキー情報も必要にはなってるので、全く何もしない状態よりはほんのちょっとセキュアではあるんですが、会社内からのアクセスに限定したいシーンなどがあると思います。いわゆる閉域化とかいうやつですね。
仮想ネットワークをAzure上に構築してプライベートエンドポイントとかVNet統合とか「ちゃんと」やろうとするとそこそこ知識や時間やお金がかかるので、今回はお手軽に関数アプリへのアクセス元を限定する設定だけ行い、ノーガードよりはちょっとセキュアな状態にしておきます。

## 関数アプリのネットワークの設定を変える
作成したばかりの今の状態は公衆ネットワークアクセスが「制限なし」になってます。クリックしてこれを変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/523bc03b-bf9f-87ab-f06f-73320d22a681.png)

公衆ネットワークのところで、「選択した仮想ネットワークとIPアドレスから有効」を選択し、サイトのアクセスルールを追加します。
例えば、キャプチャでは「10.0.0.1」とか適当なIPにしてる部分を、会社が使用しているグローバルIPとかにして規則の追加をします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/7022fd4b-60e8-90f4-9a1d-d43a4c6dba75.png)

追加したら保存して設定変更完了です。
これだけで指定したIP以外からの要求を受け付けなくなるのでお手軽です。
もちろんIPが変わらなければの前提なので、結局はどこまでやるか次第ですね
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/764cbb49-23b1-1017-7bed-d193f5cde03f.png)

おわり