Azure Functions で スクレイピングするため、Praywrightを動かす(まとめ編)

- [Azure Functions (FaaS)で スクレイピングするため、Puppeteer / Praywrightを動かしたい #AzureFunctions - Qiita](https://qiita.com/teraco/items/86006ef8636de694f2c5)
- [Azure Functions で スクレイピングするため、Praywrightを動かしたい～2つ目の関数を追加～ #AzureFunctions - Qiita](https://qiita.com/teraco/items/c771abffd0c2a6943a72)

以下の記事を自分なりにまとめて実施。コンソールはWindows環境のPowerShell
を利用

#### 1.Azure Functionsのプロジェクトディレクトリを作成

エクスプローラーから空のフォルダを作成し、そこに移動して以下のコマンドを実行

```
func init --worker-runtime node --language javascript --docker
```

#### 2.HTTP Trigger関数を作成
```
func new --name httpTrigger --template "HTTP trigger" --authlevel "anonymous"
```

#### 3.Playwrightのコードを作成

src/functions/httpTrigger.js に適当なコードを作成

#### 4.npm パッケージをインストール
Playwright の npm パッケージをインストールします。

```
npm install playwright
```

#### 5.Azureリソースを作成

1.変数を設定

Azureリソース系は今回用のユニークな名前。dockerイメージやタグは全開で作成したイメージを流用するので同じ名前。

```powershell
# Azureリソース
$RG="nhkscraiperrg"
$LOCATION="japaneast"
$APP_CONTAINER_ENV_NAME="nhkscraipercontainer"
$REGISTRY_NAME="nhkscraiperregistry"
$APP_NAME="nhkscraiperfunctionapp"
$STORAGE_NAME="nhkscraiperstorage"

# dockerイメージ
$IMAGE_NAME="nhkscraiperregistryimage"
$TAG="nhkscraiperregistrytag"
```

2.Azure CLI 拡張機能とプロバイダーの登録

```powershell
# Azure CLI 拡張機能のインストール
az extension add --name containerapp --upgrade -y

# プロバイダーの登録
az provider register --namespace Microsoft.Web
az provider register --namespace Microsoft.App
az provider register --namespace Microsoft.OperationalInsights
```

3.リソースグループを作成

```powershell
az group create --name $RG --location $LOCATION
```

4.Azure Container Apps インスタンスを作成

```powershell
az containerapp env create --name $APP_CONTAINER_ENV_NAME --resource-group $RG --location $LOCATION
```

5.Storage Account を作成

```powershell
az storage account create --name $STORAGE_NAME --resource-group $RG --location $LOCATION --sku Standard_LRS
```

6.Azure Container Registry を作成

```powershell
az acr create --name $REGISTRY_NAME --resource-group $RG --location $LOCATION --sku Basic --admin-enabled true
```
#### 6.Docker イメージをビルドして Azure Container Registry にプッシュ

1.Dockerfileを修正

```dockerfile
# To enable ssh & remote debugging on app service change the base image to the one below
# FROM mcr.microsoft.com/azure-functions/node:4-node18-appservice
FROM mcr.microsoft.com/azure-functions/node:4-node18

ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
    AzureFunctionsJobHost__Logging__Console__IsEnabled=true

COPY . /home/site/wwwroot

RUN cd /home/site/wwwroot && \
    npm install

# Install Playwright
RUN apt-get update && \
    npx playwright install-deps && \
    npx playwright install
```

2.Docker イメージをビルド

```powershell
docker build -t ${REGISTRY_NAME}.azurecr.io/${IMAGE_NAME}:${TAG} . --platform linux/amd64
# よくわからないが、↑のコマンドだと通らず、変数展開した平文だと通った。Write-hostなどで上記コマンドを実行して、平文化した後に実行すべし。
```

3.Azure Container Registry にプッシュ

```powershell
# コンテナレジストリのログインサーバーの取得
$LOGIN_SERVER = az acr show --name $REGISTRY_NAME --resource-group $RG --query loginServer --output tsv

# コンテナレジストリのユーザー名の取得
$REGISTRY_NAME = az acr credential show --name $REGISTRY_NAME --resource-group $RG --query username --output tsv

# コンテナレジストリのパスワードの取得
$ADMIN_PASSWORD = az acr credential show --name $REGISTRY_NAME --resource-group $RG --query "passwords | [0] | value" --output tsv

# Azure Container Registry にログイン
echo $ADMIN_PASSWORD | docker login $LOGIN_SERVER -u $REGISTRY_NAME --password-stdin

# Docker イメージを Azure Container Registry にプッシュ
docker push ${LOGIN_SERVER}/${IMAGE_NAME}:${TAG}
```

※ Dockerイメージは以前の作業で既にビルド済みなので、ここではビルド済みイメージを指定してAzure Container Registryにプッシュすればいいだけ…と思いきや、「Docker イメージを Azure Container Registry にプッシュ」のプロセスで失敗したので、今回用に同じイメージを作成して(↑の手順1,2)プッシュした。多分なんらかやりようはありそうだが…。

### 7. Azure Function をデプロイする

```powershell
az functionapp create --name $APP_NAME --resource-group $RG   --functions-version 4 --runtime node   --environment $APP_CONTAINER_ENV_NAME --workload-profile-name "Consumption"   --storage-account $STORAGE_NAME   --registry-server $LOGIN_SERVER --registry-username $REGISTRY_NAME --registry-password $ADMIN_PASSWORD   --image ${LOGIN_SERVER}/${IMAGE_NAME}:${TAG}
# 改行なしだと視認性が悪いので`で改行したらエラーになったので、仕方なくワンライナーにした
```

### 8. 動作確認

1.Azure FunctionsのURLを取得
```
az functionapp function show -g $RG -n $APP_NAME --function-name "httpTrigger" --query "invokeUrlTemplate" --output tsv
```
2.取得したURLに対してブラウザからアクセス

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147841/e0e66996-da8c-9159-12ca-8c5e7901fc55.png)

### 感想

手順通り上手くいきました。

が、7. Azure Function をデプロイする の後に動作確認をしたら関数側でエラーが発生しタイムアウト、と表示され全く動かず、2,3日後に思い出してリトライしたら動いた、というのがあったので、ここら辺の不安定さがどこからきているのかが分かりません。

デプロイ時だけ不安定でデプロイが終わったら安定するならいいけど…。

### 今後の課題

一度デプロイした関数を更新して実行する際の手順。

:::note info
[Azure Container Apps で最初のコンテナ化された Azure Functions を作成する | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-deploy-container-apps?tabs=acr%2Cbash&pivots=programming-language-javascript)

によると

> 関数コードに続けて変更を加える場合は、コンテナーを再構築し、イメージをレジストリに再発行し、関数アプリを新しいイメージ バージョンで更新する必要があります。 詳細については、レジストリ内のイメージ更新に関するページを参照してください。

とあるので、イメージの行進からしなければならずめんどくさい。ただ、今回の方法で作った関数はContainer Apps 環境に紐づいているので、仕方ない仕様なのかもしれない。

:::