1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Azure】Copilotと一緒にAzure Functionsを構築・公開してみた(Bicep + CLI)

Posted at

1. はじめに

1-1 ご挨拶

初めまして、井村と申します。
普段はインフラを担当していますが、開発の知識も必要だと感じる場面が増えてきました。

本記事は、前回の「ローカル環境構築編」の続きです。
今回は、Azure Functionsの基本構造の理解とAzureへのデプロイを、Copilotの支援を受けながら進めました。

作業手順を備忘録として残しておきます。

1-2 本記事の要約

1 . 本記事は以下テーブルの内容を記事にしました。

ステップ 状況
Function App の構造理解 ✅ 完了
トリガー・バインディングの理解 ✅ 完了
Azure Functions の定義確認 ✅ 完了
Azure 上へのデプロイ(Bicep + CLI) ✅ 完了
Function Key の理解とアクセス確認 ✅ 完了

2 . Azure Functions の構造理解(What / Why)

項目 What(何か) Why(なぜ必要か)
Function App 複数の関数を含むアプリ単位 ローカルとAzureで構造が共通
トリガー 関数を起動するイベント イベントドリブンな処理が可能
バインディング 外部サービスとの連携設定 コードを簡潔に保てる
__init__.py 関数ロジックを記述 Pythonで処理を定義
function.json トリガー・バインディング設定 Azureランタイムが認識するため

3 . Azureへのデプロイ(Bicep + CLI)

Azureリソースデプロイ用Bicepテンプレート

クリック展開
main.bicep
@description('作成するシステム名を指定します。')
param systemName string = 'demo'

@description('リソースグループのロケーション。今回は東日本リージョン (Japan East) を指定します。')
param location string = 'japaneast'

@description('環境を指定します。dev, stg, pro のいずれかを選択してください。')
@allowed([
  'dev'
  'stg'
  'pro'
])
param env string = 'dev'

@description('ランダムなサフィックスを生成します。')
param random string = newGuid()
var randomSuffix = toLower(substring(random, 0, 5)) // GUIDの先頭5文字を小文字で取得

@description('Functionsの名前。')
var funcName = 'func-${systemName}-${env}-${randomSuffix}'

@description('ストレージアカウントの名前。')
var stName = toLower('st${systemName}${env}${randomSuffix}')

@description('App Serviceプランの名前。')
var appServicePlanName = 'asp-${systemName}-${env}-${randomSuffix}'

@description('ストレージアカウントの接続文字列。')
var storageConnectionString = 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${listKeys(storageAccount.id, storageAccount.apiVersion).keys[0].value};EndpointSuffix=core.windows.net'


@description('ストレージアカウントを作成します。')
resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = {
  name: stName
  location: location
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'StorageV2'
  properties: {
    accessTier: 'Hot'
    supportsHttpsTrafficOnly: true
  }
}

@description('App Serviceプランを作成します。')
resource appServicePlan 'Microsoft.Web/serverfarms@2022-03-01' = {
  name: appServicePlanName
  location: location
  sku: {
    name: 'B1'
    tier: 'Basic'
  }
  properties: {
    reserved: true // Windowsの場合はfalse、Linuxの場合はtrue
  }
}

@description('Azure Functionsを作成します。')
resource functionApp 'Microsoft.Web/sites@2022-03-01' = {
  name: funcName
  location: location
  kind: 'functionapp,linux'
  properties: {
    serverFarmId: appServicePlan.id
    siteConfig: {
      linuxFxVersion: 'PYTHON|3.12' // 使用するランタイムに応じて変更(例:NODE|14, DOTNET|6など)
      appSettings: [
        {
          name: 'AzureWebJobsStorage'
          value: storageConnectionString
        }
        {
          name: 'FUNCTIONS_EXTENSION_VERSION'
          value: '~4'
        }
        {
          name: 'FUNCTIONS_WORKER_RUNTIME'
          value: 'python' // 使用するランタイムに応じて変更(例:node, python, dotnetなど)
        }
        {
          name: 'WEBSITE_RUN_FROM_PACKAGE'
          value: '1'
        }
      ]
    }
    httpsOnly: true
  }
}

実行コマンド

az login
az group create --name rg-demo-dev --location japaneast
az deployment group create --template-file main.bicep --resource-group rg-demo-dev
az resource list --resource-group rg-demo-dev --output table

4 . ローカル関数のデプロイと確認

func azure functionapp publish <AzureにデプロイされたFunctions名>

Azure Portalでの確認

  • 関数 HttpExample が表示されている
  • 関数のURLにアクセスしてレスポンス確認
https://func-demo-dev-503d5.azurewebsites.net/api/HttpExample?code=<your-function-key>&name=井村
実行結果
Hello, 井村. This HTTP triggered function executed successfully.

5 . Function Key の理解と注意点

キー種別 用途
Function Key 特定関数へのアクセス
Host Key Function App 全体へのアクセス
Master Key 管理APIへのアクセス

authLevel: "function" の場合はキーが必要。
"anonymous" に変更すると誰でもアクセス可能ですが、セキュリティには注意!

2. Coplotとのやりとり

ここからはCopilotとのやりとりになります。

2.1 井村からCopilotへの質問

ステップ1開発環境の準備は終了しました。

次は以下について教えてください。

ステップ 2: Azure Functions の基本理解
Function App の構造
トリガー(HTTP, Timer, Blob, Queue など)
入出力バインディング(Storage, Cosmos DB, Service Bus など)
Python での関数定義
__init__.py に関数ロジック
function.json にトリガー・バインディング定義

2.2 Copilotから井村への回答

素晴らしい進め方です、井村さん!  
ここでは「ステップ 2: Azure Functions の基本理解」について、以下の 5 つの観点から丁寧に解説します。

---

🧱 1. Function App の構造(全体像)
🔹 What(何か)
Azure Functions のプロジェクトは、1つの Function App に複数の関数(Function)を含む構成です。

azure-functions-python/
├── HttpExample/          ← 関数ごとのフォルダ
│   ├── __init__.py       ← 関数のロジック
│   └── function.json     ← トリガーやバインディングの定義
├── host.json             ← Function App 全体の設定
├── local.settings.json   ← ローカル実行用の環境変数
├── requirements.txt      ← Python ライブラリの依存関係
└── .vscode/              ← VS Code の設定(自動生成)

🔹 Why(なぜ必要か)
- 関数ごとに独立した設定とロジックを持てるため、拡張性が高い
- Azure 上でもこの構造がそのまま使われるため、ローカルと本番の差異が少ない

⚡ 2. トリガー(Trigger)
🔹 What(何か)
関数をいつ・どのように実行するかを決める仕組みです。代表的なトリガー:

| トリガー種別 | 説明 |
|--------------|------|
| HTTP Trigger | HTTP リクエストで関数を実行(APIとして使える) |
| Timer Trigger | cron 式で定期実行(バッチ処理など) |
| Blob Trigger | Blob Storage にファイルが追加されたとき |
| Queue Trigger | Queue Storage にメッセージが追加されたとき |

🔹 Why(なぜ必要か)
- イベントドリブンな処理を簡単に実装できる
- サーバレスの利点(必要なときだけ実行)を最大限活かせる

🔄 3. 入出力バインディング(Bindings)
🔹 What(何か)
関数が外部サービスとやり取りするための仕組みです。コード内で明示的に書かなくても、設定ファイルで連携できます。

| バインディング種別 | 説明 |
|--------------------|------|
| Input Binding | 関数が読み取るデータ(例:Blob, Cosmos DB) |
| Output Binding | 関数が書き込むデータ(例:Queue, Table, Blob) |

🔹 Why(なぜ必要か)
- コードをシンプルに保ちつつ、Azure サービスと連携できる
- 例えば「HTTP リクエスト → Cosmos DB に保存」などが簡単に実現可能

🐍 4. Python での関数定義
🔹 What(何か)
関数のロジックは `__init__.py` に Python で記述します。以下は HTTP トリガーの例:

## python
import azure.functions as func

def main(req: func.HttpRequest) -> func.HttpResponse:
    name = req.params.get('name')
    return func.HttpResponse(f"Hello, {name}!")
##

🔹 Why(なぜ必要か)
- Python の標準的な構文で記述できるため、学習コストが低い
- Azure Functions SDK(`azure-functions`)が提供する型を使って、トリガーやレスポンスを扱える

🧾 5. function.json の役割
🔹 What(何か)
関数のトリガーやバインディングの設定を記述する JSON ファイルです。例:

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

🔹 Why(なぜ必要か)
- Azure Functions ランタイムが関数の入出力を認識するために必要
- Python コードとは独立して設定できるため、柔軟性が高い
📌 まとめ図(構成イメージ)

Function App
├── Function A (HTTP Trigger)
│   ├── __init__.py
│   └── function.json
├── Function B (Timer Trigger)
│   ├── __init__.py
│   └── function.json
├── host.json
├── local.settings.json
└── requirements.txt

Functions の構造と仕組みがしっかり理解できたと思います。  
次は「Timer Trigger を追加してみる」や「Blob Storage と連携してみる」など、
実践的なトリガーやバインディングを試してみるのもおすすめです。

どの方向に進めてみたいですか?それとも、ここまでの内容を図解付きで
まとめてみましょうか?

2.3 井村からCopilotへの質問

図解まとめてほしい。

2.4 Copilotから井村への回答

jpeg.jfif

📝 図のポイント解説
🔹 Function App 全体構成
- Function App:Azure 上での実行単位(1つのアプリに複数の関数を含む)
- host.json:アプリ全体の設定
- local.settings.json:ローカル実行用の環境変数(Azure にはデプロイされない)

🔹 各関数の構成
- __init__.py:関数のロジック(Python)
- function.json:トリガーやバインディングの設定(JSON)

🔹 トリガーとバインディング
- Trigger:関数を起動するイベント(HTTP, Timer, Blob など)
- Input Binding:外部データの読み取り(例:Blob, Cosmos DB)
- Output Binding:外部サービスへの出力(例:Queue, Table)

ここからは前回ローカル端末で作成したアプリケーションをAzure上にデプロイします。Azure上には先にAzureFunctionsおよび必須サービスをBicepテンプレートを使いデプロイします。

main.bicep
main.bicep
@description('作成するシステム名を指定します。')
param systemName string = 'demo'

@description('リソースグループのロケーション。今回は東日本リージョン (Japan East) を指定します。')
param location string = 'japaneast'

@description('環境を指定します。dev, stg, pro のいずれかを選択してください。')
@allowed([
  'dev'
  'stg'
  'pro'
])
param env string = 'dev'

@description('ランダムなサフィックスを生成します。')
param random string = newGuid()
var randomSuffix = toLower(substring(random, 0, 5)) // GUIDの先頭5文字を小文字で取得

@description('Functionsの名前。')
var funcName = 'func-${systemName}-${env}-${randomSuffix}'

@description('ストレージアカウントの名前。')
var stName = toLower('st${systemName}${env}${randomSuffix}')

@description('App Serviceプランの名前。')
var appServicePlanName = 'asp-${systemName}-${env}-${randomSuffix}'

@description('ストレージアカウントの接続文字列。')
var storageConnectionString = 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${listKeys(storageAccount.id, storageAccount.apiVersion).keys[0].value};EndpointSuffix=core.windows.net'


@description('ストレージアカウントを作成します。')
resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = {
  name: stName
  location: location
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'StorageV2'
  properties: {
    accessTier: 'Hot'
    supportsHttpsTrafficOnly: true
  }
}

@description('App Serviceプランを作成します。')
resource appServicePlan 'Microsoft.Web/serverfarms@2022-03-01' = {
  name: appServicePlanName
  location: location
  sku: {
    name: 'B1'
    tier: 'Basic'
  }
  properties: {
    reserved: true // Windowsの場合はfalse、Linuxの場合はtrue
  }
}

@description('Azure Functionsを作成します。')
resource functionApp 'Microsoft.Web/sites@2022-03-01' = {
  name: funcName
  location: location
  kind: 'functionapp,linux'
  properties: {
    serverFarmId: appServicePlan.id
    siteConfig: {
      linuxFxVersion: 'PYTHON|3.12' // 使用するランタイムに応じて変更(例:NODE|14, DOTNET|6など)
      appSettings: [
        {
          name: 'AzureWebJobsStorage'
          value: storageConnectionString
        }
        {
          name: 'FUNCTIONS_EXTENSION_VERSION'
          value: '~4'
        }
        {
          name: 'FUNCTIONS_WORKER_RUNTIME'
          value: 'python' // 使用するランタイムに応じて変更(例:node, python, dotnetなど)
        }
        {
          name: 'WEBSITE_RUN_FROM_PACKAGE'
          value: '1'
        }
      ]
    }
    httpsOnly: true
  }
}

bash
# Azureへログイン
az login

# リソースグループの作成
az group create --name rg-demo-dev --location japaneast

# リソースのデプロイ
az deployment group create --template-file main.bicep --resource-group rg-demo-dev

# リソースの確認
az resource list --resource-group rg-demo-dev --output table

2.5 井村からCopilotへの質問

ローカルで作成したAzure FunctionsをAzure上にデプロイしたい。

PS C:\Users\user\Desktop\functions_work> dir .\azure-functions-python\

    Directory: C:\Users\user\Desktop\functions_work\azure-functions-python

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----          2025/08/29    15:53                __pycache__
d----          2025/08/29    15:53                .venv
d----          2025/08/29    15:53                .vscode
-a---          2025/08/29    10:30              2 .funcignore
-a---          2025/08/29    10:30            517 .gitignore
-a---          2025/08/29    10:47            879 function_app.py
-a---          2025/08/29    10:30            302 host.json
-a---          2025/08/29    10:30            149 local.settings.json
-a---          2025/08/29    10:30            147 requirements.txt

PS C:\Users\user\Desktop\functions_work> 

PS C:\Users\user\Desktop\functions_work> az resource list --resource-group rg-demo-dev --output table                 
Name                 ResourceGroup    Location    Type                               Status
-------------------  ---------------  ----------  ---------------------------------  --------
asp-demo-dev-503d5   rg-demo-dev      japaneast   Microsoft.Web/serverFarms
stdemodev503d5       rg-demo-dev      japaneast   Microsoft.Storage/storageAccounts
func-demo-dev-503d5  rg-demo-dev      japaneast   Microsoft.Web/sites
PS C:\Users\user\Desktop\functions_work> 

2.6 Copilotから井村への回答

ありがとうございます!Azure 上にすでに Function App(`func-demo-dev-503d5`)と
ストレージアカウント(`stdemodev503d5`)があるので、ローカルの Azure Functions プロジェクト
をこの Function App にデプロイする準備は整っています。

---

🚀 デプロイ手順(既存の Function App に対して)

✅ ステップ 1: Azure CLI でログイン(未ログインの場合)

## bash
az login
##

---

✅ ステップ 2: デプロイ実行

以下のコマンドを、ローカルのプロジェクトフォルダ(`azure-functions-python`)内で実行してください:

## bash
func azure functionapp publish func-demo-dev-503d5
## 

> 🔹 `func-demo-dev-503d5` は既存の Function App 名です。  
> 🔹 `requirements.txt` に記載されたライブラリが Azure 上にインストールされます。

---

✅ ステップ 3: デプロイ後の確認

1. Azure Portal にアクセス
2. `func-demo-dev-503d5` の Function App を開く
3. 「関数」メニューから `HttpExample` が表示されているか確認
4. 「コード + テスト」で関数の内容を確認
5. 「関数の URL」をコピーして、ブラウザや curl でアクセス

---

🧾 補足

- `local.settings.json` はデプロイされません。Azure 上の「アプリケーション設定」に環境変数を手動で追加する必要があります。
- `.venv` フォルダもアップロードされません。代わりに `requirements.txt` が使われます。

---

上記を試してみます。

# ディレクトリ移動(host.json)
S C:\Users\user\Desktop\functions_work> cd .\azure-functions-python\

PS C:\Users\user\Desktop\functions_work\azure-functions-python> ls

    Directory: C:\Users\user\Desktop\functions_work\azure-functions-python

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----          2025/08/29    15:53                __pycache__
d----          2025/08/29    15:53                .venv
d----          2025/08/29    15:53                .vscode
-a---          2025/08/29    10:30              2 .funcignore
-a---          2025/08/29    10:30            517 .gitignore
-a---          2025/08/29    10:47            879 function_app.py
-a---          2025/08/29    10:30            302 host.json
-a---          2025/08/29    10:30            149 local.settings.json
-a---          2025/08/29    10:30            147 requirements.txt

PS C:\Users\user\Desktop\functions_work\azure-functions-python> func azure functionapp publish func-demo-dev-503d5
Getting site publishing info...

~省略~

Deployment successful. deployer = Push-Deployer deploymentPath = Functions App ZipDeploy. Extract zip. Remote build.
Remote build succeeded!
PS C:\Users\user\Desktop\functions_work\azure-functions-python> 

001.png

002.png

004.png

上記の URL をブラウザに貼り付けてアクセスします。

https://func-demo-dev-503d5.azurewebsites.net/api/HttpExample?code=<your-function-key>&name=井村

003.png

無事にアクセスすることができました。

以下は、調査を通じて得た知識のまとめです。

Azure Functions では、関数のセキュリティを保つために 「キー(Keys)」
を使ってアクセス制御を行います。主に以下の3種類があります:

---

🔐 Azure Functions のキーの種類

| 種類 | 説明 | 用途 |
|------|------|------|
| Function Key | 特定の関数にアクセスするためのキー | 個別の関数を呼び出すときに使用 |
| Host Key | Function App 全体の関数にアクセスできるキー | 複数の関数をまとめて管理したいとき |
| Master Key | 管理者レベルのアクセス権限を持つキー | 管理 API(ログ取得など)にアクセスする際に使用 |

---

🧭 どのキーがいつ必要?

- HTTP Trigger 関数の `authLevel` が `function` の場合、Function Key または Host Key が必要です。
- `authLevel` が `anonymous` の場合、キーは不要で誰でもアクセスできます。
- Azure Portal の「テスト/実行」機能では、Function Key を自動で付与してリクエストを送っています。

---

🔍 キーの確認方法(Azure Portal)

1. Azure Portal で Function App を開く
2. 左メニューの「関数」→ 対象の関数(例:`HttpExample`)を選択
3. 上部の「関数の URL を取得」をクリック
4. 表示された URL に `?code=xxxxxxxx` が付いていれば、それが Function Key です

---

✅ 例:Function Key 付きの URL

## text
https://func-demo-dev-503d5.azurewebsites.net/api/HttpExample?code=XXXXXXXXXXXXXXXXXXXX
##

この URL にアクセスすれば、認証レベルが `function` の関数にもアクセスできます。
---

✍️ 補足:authLevel の変更

関数の `function.json` を編集すれば、認証レベルを変更できます:

## json
{
  "bindings": [
    {
      "authLevel": "anonymous",  // ← ここを変更
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": ["get", "post"]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    }
  ]
}
##

> `anonymous` にすると誰でもアクセスできるようになりますが、セキュリティには注意が必要です。
🔒 Function Key や Master Key は公開しない方が安全です。

---

❗ なぜキーを公開してはいけないのか?

🔐 Function Key の役割
- `authLevel: "function"` の関数にアクセスするための「パスワード」のようなものです。
- このキーを知っていれば、誰でも関数を実行できてしまいます。

🛡️ 公開するとどうなる?
- 意図しない第三者が関数を実行し、不正アクセスやリソース消費の原因になります。
- 特にTimer Trigger や Blob Trigger などと連携している場合、外部からの操作で予期せぬ動作が起こる可能性もあります。
---

🧼 もし誤って公開してしまったら?

1. Azure Portal で Function App を開く
2. 「関数」→ 対象関数 → 「関数キー」タブを開く
3. キーを削除 or 再生成する

3. 終わりに

ここまで読んでくださって、ありがとうございました。
Copilotとのやりとりを通じて、Azure Functions の構造理解からデプロイまで一通り学ぶことができました。
次は、Timer Trigger や Blob Trigger の実装、CI/CDの構築にも挑戦してみたいと思います。

4. 参考

5. いつか確認

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?