Azure FunctionをAzure CLIおよびAzure Function Core ToolsでNode.jsおよびPythonそれぞれをデプロイしてみた

2022年9月29日掲載

キービジュアル

Azure FunctionをAzure CLIおよびAzure Function Core ToolsでNode.jsおよびPythonそれぞれをデプロイしてみました。

目次

  • Node.jsとPythonをサーバレスで実行する環境を作りたい方向けの記事です
  • Azureの環境にデプロイする方法をステップバイステップで解説します
  • この記事を読むと、Azureで、Azure Functionにどのようにデプロイするか全体感を把握することが可能です

はじめに

Azure Functionはサーバレスコンピューティングプラットフォームであり、開発ユーザーは小さな関数らコードを作成するだけで、開発ユーザーはサーバをプロビジョニングすることなく、その関数らコードを実行することができます。

本記事では、Azure Functionのデプロイ方法の1つである、CLIベースおよびAzure Function Core Toolsを使ってNode.jsおよびPythonそれぞれをデプロイする方法を説明します。

関連記事リンク

1. 全体構成図

Azure Function上でのNode.jsおよびPythonコードをAzure CLIおよびAzure Function Core Toolsでデプロイする際の流れ、構成図としては次の通りになります。

2. Azure CLIとAzure Function Core Toolsのインストールと設定

最初に、Azure CLIコマンドツールとAzure Function Core Toolsを導入します。
Azure CLIコマンドツールおよびAzure Function Core Toolsを使用するには、それぞれのガイドラインに従ってインストールし、設定します。著者はWindowsPCを使用しているので、Windowsを例に説明します。

インストールが完了したら、`az --version``function --version`を実行してインストール状況と関連バージョンを確認します。

コマンド`func`で直接Azure Function Core Toolsのヘルプ情報を確認することもできます。

`az login`コマンドでアカウント資格情報を設定します。デフォルトのWebブラウザが開き、Azureサインインプロセスに入ります。作業環境にWebブラウザがない場合は、代わりに`az login --use-device-code`を使用することもできます。

3. Nodejsスクリプトをデプロイ - 1.Node.jsソースコードの準備

Azureの場合、最初にコンソール画面で Function App を作成する他に、ローカルからCLIで`func init`または`func new`コマンドを使ってローカルプロジェクトを初期化する必要があります。`func init` コマンドはローカルプロジェクトフォルダとその中にデフォルトの設定ファイルを作成します。`func new` コマンドはプロジェクトフォルダが完成した後に関数作成プロセスを開始します。

ここでは`func init`を例として取り上げます。

操作画面
  1. コマンドでプロジェクトの初期設定をします

  2. ランタイムはNode.jsを選択します

  3. プログラミング言語はjavascriptを選定します

プロセス全体は次のようになります。

また、インタラクティブモードではなく、コマンドラインにすべてのパラメータを置くことも可能です。

完了すると、ログとして、ローカルのプロジェクトフォルダに関連ファイルが生成されます。

今度はデプロイしたいNode.jsソースコードの準備をします。
Azure公式ドキュメントにある Quick Start with JavaScriptでは、Azure Function Core Toolsでサーバーレスとしての関数を作成する方法についてを説明しています。このサイトにはいくつかのテンプレートが用意されています。


ここでは関数コードを手動で作成しますので、コード構造がテンプレートと同じでない場合にどうすればよいかを確認することができます。

  • ローカルプロジェクトフォルダに移動
  • Functionフォルダとして使用するサブフォルダを作成
  • index.js function.json の2つのファイルを作成

参考リンク

Quick Start with JavaScript

index.jsは関数のエントリポイントであり、次のようになります。

上記のソースコードは次の通りです。

'use strict';
const moment = require('moment');

module.exports = async function (context, req) {
    context.log('JavaScript HTTP trigger function processed a request.');
    const responseMessage = "Azure CLI : " + moment().utcOffset(9).format('YYYY-MM-DD HH:mm:ss');
    context.res = {
        // status: 200, /* Defaults to 200 */
        body: responseMessage
    };
}

function.jsonは、トリガ定義を含む関数の設定です。ここでは、関数レベルで認証を行う基本的なHTTPトリガを使用します。

上記のfunction.jsonは次の通りです。

{
    "bindings": [
        {
            "authLevel": "function",
            "type": "httpTrigger",
            "direction": "in",
            "name": "req",
            "methods": [
                "get",
                "post"
            ]
        },
        {
            "type": "http",
            "direction": "out",
            "name": "res"
        }
    ]
}

ローカルプロジェクトの現在の構造は以下のようになります。

.
├── host.json
├── local.settings.json
├── package.json
└── node_test_cli
         ├── index.js
         └── function.json

npmコマンドを使用して、必要な依存パッケージをインストールします。カスタマイズされたScriptには、サードパーティの依存関係を必要とする場合があります。 上記のソースコードでは、日付を操作するためのmomentと呼ばれるパッケージが必要であり、デプロイ前に準備する必要があります。これらのパッケージはnpmでローカルに管理します。

その結果、`node_moudules`が生成されていることが確認できます。

package.jsonファイルに関連情報が正しく含まれていることを確認します。
package.jsonファイルの中にある、自動的に生成された依存関係情報がまったく使用されていない場合は、npmコマンドを実行する前に削除します。

4. Nodejsスクリプトをデプロイ - 2.Node.jsソースコードのローカルテスト

Node.jsソースコードをAzure Functionへデプロイする前に、ローカルでテストすることができます。ローカルにて `func start` を実行して、ランタイムとしてホストを起動します。その処理に引き続き、ローカルでHTTPトリガーとしてURLが表示されます。

HTTPトリガー用URLにアクセスすると、関数が実行され、処理結果が返却されます。
同時に、ターミナルにて関連ログが生成されます。

ローカルでのテストは問題ないことを確認できたので、今度はAzure Function app上でデプロイします。

5. Nodejsスクリプトをデプロイ - 3.Node.jsソースコードの展開

ソースコードの準備ができたら、今度はそのソースコードをベースとしながらAzure CLIを使用してAzure Function Appを作成します。次のように入力パラメータを指定してコマンドを入力します。ここで既存のリソースグループを使用し、コマンド`az storage account create…`で新しいストレージアカウントを作成します。

コマンドは次の通りです。

az group create --name <RESOURCE_GROUP_NAME> --location <REGION>
az storage account create --name <STORAGE_NAME> --location <REGION> --resource-group <RESOURCE_GROUP_NAME> --sku Standard_LRS

`az functionapp create … `を実行して、Azure FunctionにFunction Appを新規作成します。

コマンドは次の通りです。

az functionapp create --resource-group <RESOURCE_GROUP_NAME> \
--consumption-plan-location <REGION> --runtime node --runtime-version 16 \
--functions-version 4 --name <APP_NAME> --storage-account <STORAGE_NAME>

対象のFunction Appが使えるようになったので、コンソールから関連情報を確認することができます。

コマンド`func azure functionapp publish ohara-bob-node-cli`を使用して、作成した関数アプリに関数をデプロイします。

コマンドは次の通りです。

func azure functionapp publish <FUNCTION_NAME>

6. Nodejsスクリプトをデプロイ - 4.Function App上でデプロイ結果の確認及びテスト

コマンド入力が正しければ、Function Appへ正常にデプロイとなり、コンソール画面にてFunction App配下にFunction Nameとコード、ランタイムなどの情報が表示されます。

`Test/Run` ボタンをクリックしてスクリプトをテストします。
スクリプトを実行する前に、スクリプトの返却値は事前に定義済の日付形式を使って出力するように設定します。

Function は 関数レベルで認証されるため、生成されたHTTPトリガーに直接アクセスするとエラー(HTTP ERROR 401) が発生します。

HTTPトリガーを使用して関数をテストするには、コンソールから関数のURLを取得し、Webブラウザでテストします。

Webブラウザで開いたところ、現在の日付情報が特定の形式で表示されます。以上が、CLIベースでAzure Function上のNode.jsソースコードをデプロイする方法になります。

7. Pythonスクリプトをデプロイ - 1.Pythonソースコードの準備

今度はPythonソースコードをAzure Functionでデプロイする方法をご紹介します。ここも上記Node.jsと同様、ローカルからCLIで`func init`または`func new`コマンドを使ってローカルプロジェクトを初期化する必要があります。

Pythonスクリプト用の新しいローカルプロジェクトを開始するには、`func init`コマンドを使います。ここでは`func init`を例として取り上げます。

操作画面

このコマンドによってローカルのプロジェクトフォルダに関連ファイルが生成されます。

操作画面

今度はデプロイしたいPythonソースコードの準備をします。

`python_test_cli`という名前の関数フォルダを作成し、その中にpythonスクリプトファイル`__init__.py`と設定ファイル`function.json`を作成します。

上記のソースコードは次の通りです。

import logging

import azure.functions as func
import requests


def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    response = requests.get('http://google.com/')

    return func.HttpResponse(
        "This HTTP triggered function executed successfully. Access Google homepage with status code {0}".format(response.status_code),
        status_code=200
    )

function.jsonは、トリガ定義を含む関数の設定です。ここでは、関数レベルで認証を行う基本的なHTTPトリガを使用します。

上記のfunction.jsonは次の通りです。

{
    "scriptFile": "__init__.py",
    "bindings": [
        {
            "authLevel": "function",
            "type": "httpTrigger",
            "direction": "in",
            "name": "req",
            "methods": [
                "get",
                "post"
            ]
        },
        {
            "type": "http",
            "direction": "out",
            "name": "$return"
        }
    ]
}

ローカルプロジェクトの現在の構造は以下のようになります。

.
├── host.json
├── local.settings.json
├── requirements.txt
└── python_test_cli
        ├── __init__.py
        └── function.json

カスタマイズされたScriptには、サードパーティの依存関係が必要な場合があります。 今回のスクリプトでは、HTTP通信用ライブラリのrequestsと、Azure Function APIを介してコードを実行するためのazure-functionsという名前のサードパーティパッケージが必要であり、デプロイ前にローカルで準備する必要があります。これらのパッケージはpipを使用してローカルで管理します。

`pip3 install <パッケージ名> -t .` コマンドを実行して必要なパッケージをローカルにインストールすると、index.pyに関連するパッケージフォルダができます。

requirements.txtに依存関係の情報が正しいかどうかを確認します。

上記の構成情報は次の通りです。

# Do not include azure-functions-worker as it may conflict with the Azure Functions platform

azure-functions
requests

8. Pythonスクリプトをデプロイ - 2.Pythonソースコードのローカルテスト

PythonソースコードをAzure Functionへデプロイする前に、ローカルでテストすることができます。ローカルにて `func start` を実行して、ランタイムとしてホストを起動します。その処理に引き続き、ローカルでHTTPトリガーとしてURLが表示されます。

HTTPトリガー用URLにアクセスすると、関数が実行され、処理結果が返却されます。
同時に、ターミナルにて関連ログが生成されます。

ローカルでのテストは問題ないことを確認できたので、今度はAzure Function app上でデプロイします。

9. Pythonスクリプトをデプロイ - 3.Pythonソースコードの展開

ソースコードの準備ができたら、今度はそのソースコードをベースとしながらAzure CLIを使用してAzure Function Appを作成します。上記Node.jsと同じく、次のように入力パラメータを指定してコマンドを入力します。ここで既存のリソースグループを使用し、コマンド`az storage account create…`で新しいストレージアカウントを作成します。

コマンドは次の通りです。

az functionapp create --resource-group  \
--consumption-plan-location japaneast --runtime python --runtime-version 3.8 \
--functions-version 4 --name  --os-type linux \
--storage-account 

コマンドは次の通りです。

func azure functionapp publish <FUNCTION_NAME>

Linux上のPythonスクリプトは、デフォルトでリモートからビルドされます。ローカルで生成されたZIPファイルからFunction Appへのデプロイはされません。requirements.txtに何か問題がある場合、ビルド処理が失敗に終わりますので注意する必要があります。

10. Pythonスクリプトをデプロイ - 4.Function App上でデプロイ結果の確認及びテスト

コマンド入力が正しければ、Function Appへ正常にデプロイとなり、コンソール画面にてFunction App配下にFunction Nameとコード、ランタイムなどの情報が表示されます。

`Test/Run` ボタンをクリックしてスクリプトをテストします。

操作画面

Function は 関数レベルで認証されるため、生成されたHTTPトリガーに直接アクセスするとエラー(HTTP ERROR 401) が発生します。

HTTPトリガーを使用して関数をテストするには、コンソールから関数のURLを取得し、Webブラウザでテストします。

テストの結果、HTTP 200が無事返却されたので、成功です。以上が、CLIベースでAzure Function上のNode.jsソースコードをデプロイする方法になります。

11. 補足事項

・エラー"Value cannot be null.(Parameter'provider')"の修正方法

ローカルで実行中のプロセスで、"Value cannot be null.(Parameter'provider')"などのエラーが発生することがあります。

これは、自動的に生成されたhost.jsonに事前定義された拡張バンドルによって引き起こされる。

拡張バンドルが正しくインストールされないと、関連するエラーが発生します。実行中に詳細を確認するには、`func host start --verbose`コマンドを使用してください。

私の場合、スクリプトがこのURLから拡張バンドルをダウンロードしようとしていることがわかります。これには、ネットワークの状態によって時間がかかる場合があります。

一方、host.jsonに記述されていない他の拡張バンドルが必要な場合は、すべての拡張に対して`func extensions install`コマンドを使用するか、特定の拡張バンドルに対して `func extensions install --package Microsoft.Azure.Functions.ExtensionBundle --version 3.11.0` コマンドを使用できます。

この場合、ターゲット拡張バンドルはhost.jsonに設定されているため、このコマンドでこれ以上のアクションは実行されません。

あるいは、必要がなければ、host.jsonから拡張バンドルを削除することもできます。この状況では、拡張によるアクションはありません。

・依存関係をローカルで修正する方法

このエラーは依存関係によって発生します。これはプログラミング言語で行うのと同じように修正できます。Node.jsでは、package.jsonとnpmコマンドで修正されます。

・ランタイムとOS間のマッピングエラーを修正する方法

Pythonスクリプト用の関数アプリを作成するときにos typeをlinuxに設定しないと、マッピングエラーが発生します。これは、Pythonがデフォルトのosウィンドウでサポートされていないためです。

`az functionapp list-runtimes`コマンドを使えば、runtimeとosの関係を調べることができます。

12. 最後に

Azure Function をCLIベースでNode.jsおよびPythonそれぞれをデプロイする方法をご紹介しました。サーバレスアプリケーションはコードを記述しながら実行できるクラウドサービスなので、エンジニアリングリソースを小さくしてくれるため非常に便利です。一方、複数の開発者による並列操作、環境構成の管理、ランタイムで例えばPythonのバージョン変更など各環境で些細な変更が生じても素早く変更、自動的にデプロイしたい場合は、コンソール画面での操作では手入力等反映リソースが追いつかなくなるため、Infrastructure as Code(IaC)ベースで運用するのがベターです。

本記事では、IaCを意識しながらAzure CLIコマンドツールおよびAzure Function Core Toolsを介して、ローカルにあるソースコードをローカル内でテストしてからAzure Functionへ直接アップロード保存し、そのままイベント操作をする方法を記載していますので、CI/CDパイプラインでサーバレスアプリケーションを構築する際はご参考になれば幸いです。

関連記事リンク

サーバレスってなに?Alibaba Cloud, AWS, Azure, Google Cloud のサーバレスサービスを比べてみました

AWS

AWS LambdaにZIPファイル化したNode.jsおよびPythonのコードをデプロイしてみた(GUI編)

AWS LambdaをAWS CLIベースでNode.jsおよびPythonそれぞれをデプロイしてみた(CLI編)

AWS ECRを使ってNode.js/PythonのコンテナイメージをAWS Lambdaへデプロイしてみた

Google Cloud

Google Cloud FunctionにZIPファイル化したNode.jsおよびPythonのコードをデプロイしてみた(GUI編)  ← 本記事

Google Cloud FunctionをGoogle Cloud CLIベースでNode.jsおよびPythonそれぞれをデプロイしてみた(CLI編)

Azure

Azure FunctionにZIPファイル化したNode.jsおよびPythonのコードをデプロイしてみた(GUI編)

Azure FunctionをAzure CLIベースおよびAzure Function Core ToolsでNode.jsおよびPythonそれぞれをデプロイしてみた(CLI編)

Azure FunctionをAzure CLIおよびAzure Function Core ToolsでNode.jsおよびPythonそれぞれをデプロイしてみた  ← 本記事

Alibaba Cloud

Alibaba Cloud Function ComputeにZIPファイル化したNode.jsおよびPythonのコードをデプロイしてみた(GUI編)

Alibaba Cloud FunctionComputeをCLIベースでNode.jsおよびPythonそれぞれをデプロイしてみた(CLI編)

Serverless Devsを使ってNode.js/PythonコードをコンテナイメージにしながらAlibaba Cloud FunctionComputeへデプロイしてみた

関連サービス

Microsoft Azure

Microsoft Azureは、Microsoftが提供するパブリッククラウドプラットフォームです。コンピューティングからデータ保存、アプリケーションなどのリソースを、必要な時に必要な量だけ従量課金で利用することができます。

MSPサービス

MSP(Managed Service Provider)サービスは、お客さまのパブリッククラウドの導入から運用までをトータルでご提供するマネージドサービスです。

おすすめの記事

条件に該当するページがございません