概要
公式のドキュメントにはリソースグループを作成するところからの説明があるのですが、既に存在するリソースグループの中にFunctionsをデプロイする方法については書かれていないようでしたので書きます。
公式ドキュメント:
コマンド ラインから JavaScript 関数を作成する - Azure Functions | Microsoft Learn
https://learn.microsoft.com/ja-jp/azure/azure-functions/create-first-function-cli-node?tabs=azure-cli%2Cbrowser&pivots=nodejs-model-v4
なおJavascript関数を作成すると書いてありますが、基本的にデプロイまではシェルスクリプトを用いますので、あまり言語によって限定されるお話でもないと思いますが、やはりJavascriptを使っていただくのが参考コードをそのまま使えて良いと思います。
この記事のPythonバージョンは以下よりご覧いただけます。
AzureのFunctionsをCLIで使う(ローカルリソースの生成からデプロイまで)with Python - Qiita
https://qiita.com/fsd_yoshikawa/items/11a0b67c89588be47576
環境
Windows11, WSL2
❯ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=22.04
DISTRIB_CODENAME=jammy
DISTRIB_DESCRIPTION="Ubuntu 22.04.1 LTS"
node.js
❯ node --version
v18.15.0
Azure CLI
❯ az --version
azure-cli 2.46.0 *
core 2.46.0 *
telemetry 1.0.8
Dependencies:
msal 1.20.0
azure-mgmt-resource 21.1.0b1
Azure Functions Core Tools
❯ func --version
4.0.5030
手順
前提として、まずはAzure上にリソースグループを持っていることが必要です。
ログイン
まずはCLIでAzureにログインします。
az login --use-device-code
上記のコマンドを実行すると、https://microsoft.com/deviceloginというURLとcode(大文字英数字)のペアがターミナル上に表示されます。このcodeをコピーして表示されたURLに行って入力するとAzureにログインできます。
Azure上にストレージの作成
Functionsを使うにはストレージが必要になりますので、まずはこれを作成します。
az storage account create --name <STORAGE_NAME> --resource-group <RESOURCE_GROUP_NAME>
<>の中の文字列はご自分の環境に合わせて入力してください。
Azure上にFunctions Appリソースの作成
az functionapp create --consumption-plan-location japaneast --runtime node --runtime-version 18 --functions-version 4 --name <APP_NAME> --os-type linux --storage-account <STORAGE_NAME> --resource-group <RESOURCE_GROUP>
私の場合では上記<LOCATION>はjapaneastを設定しました。
<STORAGE_NAME>はストレージの作成の項目で作ったストレージの名前を入力します。
上記で --runtime-version 18
の指定はローカルにインストールされているnodeのバージョンに依ります。
--functions-version 4
の指定については下記のURLに説明があります。
Azure Functions ランタイム バージョンの概要 | Microsoft Learn
https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-versions?tabs=v4&pivots=programming-language-csharp
Functionsにデプロイするローカル環境の作成
func init azure-functions --node
上記のコマンドを実行すると、下記のようなファイル群が生成されます。
.
└── azure-functions
├── host.json
├── local.settings.json
└── package.json
生成したディレクトリに移動します。
cd azure-functions
次に、Functions上で実行されるエントリーポイントをテンプレートを用いて作成します。
func new --name test --template "HTTP trigger"
するとtestディレクトリが新たに生成されて、下記のようなディレクトリ構造になります。
.
└── azure-functions
├── host.json
├── local.settings.json
├── package.json
└── test
├── function.json
└── index.js
このtestディレクトリ内のindex.jsにAzure Functionsで動作するコードを書くことになります。
デフォルトでは以下のような状況になってます。
module.exports = async function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
const name = (req.query.name || (req.body && req.body.name));
const responseMessage = name
? "Hello, " + name + ". This HTTP triggered function executed successfully."
: "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.";
context.res = {
// status: 200, /* Defaults to 200 */
body: responseMessage
};
}
これがどういう動作をするかテストするにはazure-functionsディレクトリで以下のコマンドを実行します。
func start
すると以下のような出力が得られます。
❯ func start
Azure Functions Core Tools
Core Tools Version: 4.0.5030 Commit hash: N/A (64-bit)
Function Runtime Version: 4.15.2.20177
Functions:
test: [GET,POST] http://localhost:7071/api/test
For detailed output, run func with --verbose flag.
[2023-04-11T04:34:07.934Z] Worker process started and initialized.
[2023-04-11T04:34:12.365Z] Host lock lease acquired by instance ID '000000000000000000000000017436A7'.
この http://localhost:7071/api/test にアクセスすると、このコードをFunctions上にデプロイするとどういう振る舞いをするかのテストがローカルマシン上でできます。
試しにアクセスすると
This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.
とブラウザ上に表示されたかと思います。
Azure上にデプロイ
次に下記のコマンドを実行するとAzure上にFunctionsをデプロイできます。
func azure functionapp publish <APP_NAME>
<APP_NAME>はFunctionsリソースの作成の項で設定した文字列を用います。
Azure Functions上での機能ごとのファイル分割について
これでAzure Portal上で作成したFunctionsを使用することができるようになるのですが、実際的にFunctionsを使用する際、外部のモジュールを使用したり、機能ごとにファイルを分割したいということがあります。
そこで、index.jsと同じ階層に、libディレクトリを切って、そこにクラスが記述されたファイルを配置し、それをindex.jsで呼び出すというテストを行います。
まずは、azure-functions/testディレクトリでmkdir lib
を実行します。
そしてtouch lib/write-hello.js
でwrite-hello.jsを作成します。
次にwrite-hello.jsの内容を次の通りに変更します。
class TestClass {
writeHello(){
return "HELLO from a external file."
}
}
module.exports = TestClass;
つづいて、index.jsを以下の通りに変更します。
module.exports = async function (context, req) {
const TestClass = require("./lib/write-hello")
const test = new TestClass();
const responseMessage = test.writeHello();
context.res = {
// status: 200, /* Defaults to 200 */
body: responseMessage
};
}
コードの内容としてはindex.jsからwrite-hello.jsの"HELLO from a external file."の文字列を呼び出してindex.jsのresponseMessageに代入、これをhttp responseとして返すという形です。
この構造にしてpublish
(またはfunc start
でテスト)して、エンドポイントURLにアクセスした結果以下の表示が得られれば成功です。
HELLO from a external file.
ファイルを分割してAzure Functions上に乗せることができました。
ただし、このような構造でAzure Functions上にアップロードしたとして、現在のところAzure Portal上でlib以下のファイルについては見ることができないようなのでご注意ください。
以上です。