Azure Functions をwindows の IIS へ Deploy して動かす

#はじめに

基本は　[この記事](https://dev.to/gjcampbell/running-azure-functions-in-iis-32a)　にかいてるけど、オレも含めて一度は失敗してハマるから覚書する

それと、そんな必要あんの？と思うけど、functionsで処理が閉じていれば必要ないが、その向こう側に作成する予定の別APIを開発者がローカルで一気通貫テストしたいと要望あって、ここに行きついた

ただ、ひっくるめて、ソースもらってデバックするのが一番早いかもね

##インストールするもの

+ ASP.Net Core Runtime
+ Hosting Bundle

の二つ

https://dotnet.microsoft.com/download/dotnet/3.1


![スクリーンショット 2021-04-10 200742.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439179/b61c60bd-76e8-a3db-013e-12450a215a0a.png)

ダウンロードして、インストールする。

##ダウンロードするもの

+ Functions.3.0.14191.zip

https://github.com/Azure/azure-functions-host/releases/tag/v3.0.14191


Functions.3.0.14191.zipをダウンロードした後、IISのサイトフォルダに解凍する
たとえば、こんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439179/0b68cbd2-1e80-5a61-2138-9529dc05836b.png)

F:\WebApp\hosting
に解凍

正直、解凍するフォルダはどこでもよくて C:\Toolsなんて自分専用のツール格納群フォルダでもいいけど、あとでFunctionsをデプロイした後に、このフォルダの中にある Microsoft.Azure.WebJobs.Script.WebHost.exe へのパスを web.config ファイルへ記述する作業が出てくる。
その際に、絶対パスで記述する事になるが、後々面倒を起こす（開発者毎に設定する必要があって、たいてい一人くらいは動かないと手を挙げる人が出てくる）から、最初からWEBフォルダの中につっこんでおいて、web.config に相対パスで記述して配布すると、面倒が出なくていい。今回は web 用のフォルダに突っ込んでおく。

ちなみに、Microsoft.Azure.WebJobs.Script.WebHost.exe　は

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439179/3cb6fb0b-ec13-aa95-af4a-6ba0d6506ff9.png)

ここにあるけど、今どきのPCは 64bit なので、次のパスをメモ帳あたりにメモっておく

+ F:\WebApp\hosting\3.0.14191\64bit\Microsoft.Azure.WebJobs.Script.WebHost.exe
 

次に、ここに site フォルダ作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439179/210161cf-8b99-7ba2-1435-ca3a7e20d1e9.png)


site フォルダの中に次の空のフォルダを作成

+ CSharp
+ Java
+ Node
+ powershell
+ Python

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439179/4ad3b9dd-a193-58de-c09c-a71f5644a5cb.png)


各言語で作成した functions をここに配置するため。

次にローカルIISにデプロイしたい対象のFunctionsプロジェクトから、フォルダーにPublishする
たとえば、VisualStudioだと、発行ツール経由で、フォルダにPublishできる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439179/1253e58a-e46a-8798-c4eb-4ceee6dae50a.png)

今回、適当な httptrigger の get要求で文字返すAPIをC#で作った。
↑の中で作成した空フォルダの中では、CSharpフォルダへデプロイする
![スクリーンショット 2021-04-10 205826.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439179/f71cd77c-8d04-99d8-882e-930604b1b139.png)

無事デプロイできた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439179/e9194464-7d00-ea34-b201-bab0e1ecad7f.png)

host.json が設定ファイルになる。
各種設定があるなら、ここで編集して設定する。
たとえば、AzureWebJobsStorageみたいな設定のこと

## web.config の作成
先ほどデプロイしたフォルダに web.config ファイルを新規作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439179/5d136291-c900-dd93-99df-899526f00a8b.png)

中身はコレをコピペで張り付け

```XML:web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <!-- To customize the asp.net core module uncomment and edit the following section. 
  For more info see https://go.microsoft.com/fwlink/?linkid=838655 -->
  <system.webServer>
    <handlers>
      <remove name="aspNetCore" />
      <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
    </handlers>
    <aspNetCore processPath="..\..\3.0.14191\64bit\Microsoft.Azure.WebJobs.Script.WebHost.exe" 
      arguments="" stdoutLogEnabled="false" startupTimeLimit="3600" 
      stdoutLogFile=".\logs\stdout" hostingModel="InProcess" />
    <httpProtocol>
      <customHeaders>
        <remove name="X-Powered-By" />
      </customHeaders>
    </httpProtocol>
    <security>
      <requestFiltering allowDoubleEscaping="true" removeServerHeader="true">
        <requestLimits maxQueryString="4096" maxUrl="8192" maxAllowedContentLength="104857600" />
      </requestFiltering>
    </security>
  </system.webServer>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.4.0.0" newVersion="4.0.2.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>
```

aspNetCore の prosessPath がキモで、これがさっきメモ帳に退避した、Microsoft.Azure.WebJobs.Script.WebHost.exeへのパスになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439179/0f1f443e-4644-b1a8-b9b2-6f01735f8938.png)

開発者にフォルダ毎配ると面倒がないので、相対パスで記述できるようにした方がよいと思う。


#windows IIS の設定

さっきのweb.config見るとわかるけど、InProcessで exe を動かすことになるので、アプリケーションプールには管理者権限が必要になる。

##アプリケーションプールの追加

IISマネージャーを起動して、アプリケーションプールを右クリック、プールの追加を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439179/65ee386d-92da-c2be-e312-b1d722e5df89.png)

名前はなんでもいいから適当につけて追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439179/404a5d97-5f88-86fb-654a-d243c17550f2.png)


作ったプールの詳細設定から、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439179/2fc993b0-4827-96e0-0c1e-21939d54a470.png)

プロセスモデルのIDをデフォルトのApplicationPoolIdentityから、...を元に
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439179/2acea9dd-cb9a-b12d-c2de-006d91cd9ccf.png)

ビルトインアカウントをカスタムアカウントに変えて、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439179/cdac6a66-7c73-ca1c-55f6-149c586397b2.png)

自分のローカルPCの管理者権限のあるユーザーに変更する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439179/2088f986-16a6-af41-b709-c47b5d3b235c.png)

FunctionsはEXE経由で実行することになるから、IISの権限だと動かない


次に、Default WebSite を右クリックしてアプリケーションの追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439179/a5676d02-3374-7110-be56-2bea94415a9d.png)

エイリアス名は適当に付けて、アプリケーションプールはさっき作成した管理者権限のあるプールを選択

![スクリーンショット 2021-04-10 215400.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439179/eb15e7e2-8ff3-9175-9c08-ed935eb11993.png)


物理パスは、さっき functions をデプロイして、web.configを配置したパスを指定

設定はこれで全て完了。

サイトもローカルIISにできた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439179/7181dcb5-fee9-2346-8827-54e22416c37f.png)

URLは Azure Functions と同じで、api/xxx になる
![スクリーンショット 2021-04-10 214559.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439179/ba63a10d-848d-8f0e-c304-eb8900265875.png)


# 補足
Functions の authLevel が anonymous 以外だと動かないと思うので、デプロイした フォルダの中にある function.json を直接編集して、anonymous にするとよい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439179/d1355289-bc23-8305-ba2e-0140faa5e619.png)

![スクリーンショット 2021-04-10 214953.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439179/6a03d2f6-eb91-e0cf-4b53-de110f3ca94f.png)