Azure Functions×DevContainer環境構築|Python 3.11編

はじめに

どうも、龍ちゃんです!

前回の「Azure Functions×DevContainer 環境構築| Node.js 編」では、Node.js 22 + TypeScript を使った DevContainer 環境構築を解説しました。今回は、Python 3.11 を使った Azure Functions の開発環境を構築します。

📦 サンプルリポジトリ: 本記事で解説する環境をすぐに試せるサンプルコードを公開しています。

なぜ Python で Azure Functions なのか?

単純な REST API の実装であれば、Node.js と Python のどちらでも問題ありません。

しかし、以下のような特定のライブラリや数値計算が必要な要件がある場合は、Python を選択すべきです:

  • データ処理: pandas、NumPy を使った大量データの前処理・集計
  • 機械学習: scikit-learn、TensorFlow モデルの推論
  • 数値計算: SciPy、SymPy を使った科学技術計算
  • スクレイピング: BeautifulSoup、Scrapy を使った Web スクレイピング

Python を選ぶ判断基準:

  • pandas / NumPy / scikit-learn などのライブラリが必須
  • 既存の Python コードやモデルを Azure Functions で動かしたい
  • データサイエンスチームが Python を使っている

Node.js を選ぶ判断基準:

  • 単純な REST API やリアルタイム処理
  • TypeScript で型安全な開発がしたい
  • npm エコシステムのライブラリを活用したい
項目 Node.js 版 Python 版
適した用途 REST API、リアルタイム処理 データ処理、機械学習、数値計算
ライブラリ npm エコシステム pandas、NumPy、scikit-learn
非同期処理 async/await が得意 asyncio があるが Node.js ほど主流ではない
学習コスト TypeScript の型定義 Python の動的型付け

今回も DevContainer を使うことで、チーム開発での再現性を確保します。

本記事の前提

  • Azure Functions×DevContainer 環境構築| Node.js 編 を読んでいることを推奨
  • Node.js 編と共通の前提条件(Docker Desktop、VSCode、Dev Containers 拡張機能)が必要です
  • Docker Desktop がインストール済みであること
  • Visual Studio Code がインストール済みであること
  • Dev Containers 拡張機能 がインストール済みであること
    • VSCode の拡張機能パネルから「Dev Containers」をインストール
  • Python の基本文法 を理解していること

それでは、Python 版の DevContainer 環境構築を始めましょう!

Azure Functions とは?(簡潔版)

詳細は Node.js 編 を参照してください。ここでは、Python 版で重要なポイントのみ記載します。

Python で使える主要なトリガー

トリガー 用途 Python での利用例
HTTP Trigger REST API データ分析 API、機械学習推論 API
Timer Trigger 定期実行 毎日深夜にデータ集計・レポート作成
Blob Trigger ファイル処理 CSV アップロード時の pandas 処理
Queue Trigger 非同期処理 大量データの分散処理

必要なツール一覧

Python 版でも、Node.js 版と同じツール構成です:

ツール名 バージョン インストール先
Docker Desktop 最新 ホスト OS
Visual Studio Code 最新 ホスト OS
Dev Containers 拡張機能 最新 VSCode
Python 3.11.x DevContainer 内で自動
Azure Functions Core Tools v4.x DevContainer 内で自動
Azurite 最新 DevContainer 内で自動

重要:

  • Python 版の Azure Functions でも、Azure Functions Core Tools は Node.js 製!DevContainer 内に Node.js もインストールされます
  • ホスト OS には Python をインストール不要(すべて DevContainer 内で完結)

Python DevContainer の構築

これから構築する環境の全体像を把握しましょう。

構築後のディレクトリ構成

azure-functions-python-devcontainer/     # プロジェクトルート
├── .devcontainer/                       # DevContainer 設定
│   ├── Dockerfile                       # コンテナイメージ定義(方式1の場合)
│   └── devcontainer.json                # DevContainer 設定ファイル
│
└── MyPythonFunctionApp/                 # Azure Functions プロジェクト
    ├── .funcignore                      # デプロイ除外ファイル
    ├── .gitignore                       # Git 除外設定
    ├── .venv/                           # Python 仮想環境(作成後)
    │   ├── bin/                         # 実行ファイル
    │   ├── lib/                         # インストール済みパッケージ
    │   └── pyvenv.cfg                   # 仮想環境設定
    ├── host.json                        # Functions ランタイム設定
    ├── local.settings.json              # ローカル環境変数
    ├── requirements.txt                 # Python 依存関係
    │
    └── function_app.py                  # メイン関数ファイル
                                         # すべての関数を定義

Node.js 版との違い:

  • package.json の代わりに requirements.txt
  • src/functions/*.ts の代わりに function_app.py 1 ファイル
  • .venv/ で Python 仮想環境を管理

ポイント:

  • .devcontainer/ で開発環境を定義
  • MyPythonFunctionApp/ が実際の Functions プロジェクト
  • Python の関数はすべて function_app.py に記述(Node.js版とは違い、1ファイルにまとめる)

構築方法

Python 版の DevContainer 構築には、主に 2 つの方法があります:

  1. Dockerfile 方式 – カスタム Dockerfile で詳細に制御(推奨
  2. DevContainer Features 方式 – 既存イメージに Node.js を追加

Python では Dockerfile 方式を推奨する理由:

  • Python はバージョン依存が強いため、明示的なバージョン指定が重要です
  • Features 方式だと、VSCode の Python Interpreter 設定で意図しない Python 環境が選ばれることがあるんですよね
  • Dockerfile 方式なら、Python 3.11 を確実に指定できる!
  • 再現性が高く、チーム開発で環境差異が発生しにくい

注意: 参考記事(Claude Code×DevContainer)では Features 方式を推奨していますが、Python の場合は Dockerfile 方式の方が確実です。

方法 1: Dockerfile 方式(推奨)

Python ベースイメージから、Node.js を手動でインストールする方式です。

この方式の利点:

  • Python 3.11 を確実に指定できる
  • 意図しない Python 環境が選ばれるリスクがない
  • ビルド時に全依存関係がインストールされるため、起動が高速

ステップ 1: プロジェクトディレクトリの作成

mkdir azure-functions-python-devcontainer
cd azure-functions-python-devcontainer
mkdir .devcontainer

ステップ 2: Dockerfile の作成

.devcontainer/Dockerfile:

# .devcontainer/Dockerfile
FROM mcr.microsoft.com/devcontainers/python:3.11

# Node.js のインストール(Azure Functions Core Tools に必要)
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - \
    && apt-get install -y nodejs

# 作業ディレクトリ
WORKDIR /workspace

# 実行ユーザー
USER vscode

# npm のグローバルインストール先を vscode ユーザーのホームディレクトリに設定
RUN mkdir -p /home/vscode/.npm-global \
    && npm config set prefix '/home/vscode/.npm-global'

# PATH に npm グローバルディレクトリを追加
ENV PATH="/home/vscode/.npm-global/bin:${PATH}"


# Azure Functions Core Tools と Azurite のインストール
RUN npm install -g \
    npm@11.5.2 \
    azure-functions-core-tools@4 \
    azurite

# バージョン確認用コマンド(デバッグ用)
RUN echo "=== Installed Versions ===" \
    && python --version \
    && pip --version \
    && node --version \
    && npm --version \
    && func --version \
    && echo "========================="

# デフォルトコマンド
CMD ["sleep", "infinity"]

ポイント:

  • mcr.microsoft.com/devcontainers/python:3.11 は Microsoft 公式の Python 3.11 イメージ
  • Node.js をインストール(Azure Functions Core Tools が Node.js 製のため必須!)
  • vscode ユーザーで実行(Python イメージのデフォルトユーザー)

ステップ 3: devcontainer.json の作成

.devcontainer/devcontainer.json:

{
  "name": "Azure Functions Python DevContainer",
  "build": {
    "dockerfile": "./Dockerfile"
  },
  "workspaceFolder": "/workspace",
  "remoteUser": "vscode",

  "forwardPorts": [7071, 10000, 10001, 10002],

  "customizations": {
    "vscode": {
      "extensions": [
        "ms-azuretools.vscode-azurefunctions",
        "ms-python.python",
        "ms-python.vscode-pylance",
        "ms-python.black-formatter"
      ]
    }
  }
}

ポイント:

  • ms-python.python: Python 拡張機能
  • ms-python.vscode-pylance: 型チェック・インテリセンス
  • ms-python.black-formatter: Python コードフォーマッタ

方法 2: DevContainer Features 方式(代替案)

DevContainer Features を使うと、Node.js のインストールが 1 行で完了します。

この方式の注意点:

  • シンプルだが、Python Interpreter が意図しない環境を指す場合がある
  • DevContainer 起動後に必ず Interpreter 設定を確認する必要がある
  • Features 方式でも問題ない場合もあるが、Dockerfile 方式の方が確実

.devcontainer/devcontainer.json:

{
  "name": "Azure Functions Python DevContainer",
  "image": "mcr.microsoft.com/devcontainers/python:3.11",
  "workspaceFolder": "/workspace",
  "remoteUser": "vscode",

  "features": {
    "ghcr.io/devcontainers/features/node:1": {
      "version": "lts"
    }
  },

  "postCreateCommand": "npm install -g npm@11.5.2 azure-functions-core-tools@4 azurite",

  "forwardPorts": [7071, 10000, 10001, 10002],

  "customizations": {
    "vscode": {
      "extensions": [
        "ms-azuretools.vscode-azurefunctions",
        "ms-python.python",
        "ms-python.vscode-pylance",
        "ms-python.black-formatter"
      ]
    }
  }
}

ポイント:

どちらの方式を選ぶか:

  • Dockerfile 方式を推奨 – Python バージョンを確実に制御できる
  • Features 方式は、Python Interpreter 設定に注意すれば使える

DevContainer の起動

  1. VSCode で azure-functions-python-devcontainer フォルダを開く
  2. 左下の「>」アイコンをクリック
  3. Reopen in Container」を選択
  4. Docker イメージのビルドと起動が開始されます

成功すると:

  • VSCode の左下に「Dev Container: Azure Functions Python DevContainer」と表示

⚠️ 重要: Python Interpreter の設定確認

DevContainer 起動後、必ず Python Interpreter が正しく設定されているか確認してください。

  1. VSCode のコマンドパレットを開く(Ctrl+Shift+P / Cmd+Shift+P
  2. Python: Select Interpreter」を検索・選択
  3. /usr/local/bin/python または /usr/bin/python3.11 が選択されていることを確認

よくある問題:

  • 意図しない Python 環境(例: /usr/local/python/current/bin/python)が選ばれている
  • この場合、手動で /usr/local/bin/python を選択し直す

Python バージョンの確認:

python --version
# → Python 3.11.x と表示されること

Python はバージョン依存が強いため、この確認は必須です!Python 3.11 以外が選ばれていると、ライブラリの互換性問題が発生してハマります。

Functions プロジェクトの作成

DevContainer 内で Azure Functions プロジェクトを作成します。

プロジェクト初期化

DevContainer 内のターミナルで実行:

func init MyPythonFunctionApp --python
cd MyPythonFunctionApp

生成されるファイル:

MyPythonFunctionApp/
├── .funcignore            # Functions デプロイ時の除外ファイル
├── .gitignore             # Git 除外設定
├── host.json              # Functions ランタイム設定
├── local.settings.json    # ローカル環境変数
├── requirements.txt       # Python 依存関係
└── function_app.py        # メイン関数ファイル(初期状態は空)

Node.js 版との違い:

  • package.json の代わりに requirements.txt
  • src/ ディレクトリの代わりに function_app.py

local.settings.json の設定

local.settings.json を編集して、Azurite 接続設定を追加:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "python"
  }
}

重要:

  • FUNCTIONS_WORKER_RUNTIME: "python" を設定
  • AzureWebJobsStorage は Node.js 版と同じ

Python 仮想環境の作成

Python 版では、仮想環境を作成することを推奨します。

# 仮想環境の作成
python -m venv .venv

# 仮想環境の有効化
# Linux/macOS
source .venv/bin/activate
# Windows (PowerShell)
.venv\Scripts\Activate.ps1

仮想環境を使う理由:

  • プロジェクトごとに依存関係を分離できる
  • 他のプロジェクトとのライブラリバージョン競合を回避できる

🤔 コラム: 仮想環境内に仮想環境を作る

DevContainer(コンテナ仮想環境)の中で .venv(Python 仮想環境)を作るのは、一見冗長に見えるかもしれません。しかし、この二重構造には実用的なメリットがあります:

1. グローバル環境の混入を防ぐ
.venv を使わないと、開発者個人の Python 環境にインストールされているライブラリが紛れ込む可能性があります。例えば、開発者 A は pandas をグローバルにインストールしているが、開発者 B はインストールしていない場合、「自分の環境では動くのに…」という問題が発生します。

2. requirements.txt の汚染を防ぐ
.venv を有効化し忘れてパッケージをインストールすると、全然関係ないライブラリまで requirements.txt に追記される…これ、Python 開発あるあるですよね

# ❌ .venv を有効化し忘れてインストール
pip install pandas
pip freeze > requirements.txt
# → グローバル環境の不要なライブラリまで記録される!

# ✅ .venv を有効化してからインストール
source .venv/bin/activate
pip install pandas
pip freeze > requirements.txt
# → プロジェクト専用のライブラリのみ記録される

3. 開発環境の使いまわしが可能
同じ DevContainer を複数のプロジェクトで「ロンダリング」(使いまわす)しても、.venv があることで各プロジェクトの依存関係が混ざりません。プロジェクト A 用の .venv とプロジェクト B 用の .venv を独立して管理できます。

個人的には、この二重仮想環境構成は好みですね。予期しない依存関係の混入を確実に防げます!

依存関係のインストール

pip install -r requirements.txt

⚠️ 注意: requirements.txt の管理

pip install でライブラリを追加しても、requirements.txt には自動的に追記されません。ここ、Node.js の package.json と違って手動管理が必要なんですよね:

# ライブラリをインストール
pip install pandas

# requirements.txt を更新
pip freeze > requirements.txt

発展的な選択肢: uv の活用

より効率的な依存関係管理には、uv(高速 Python パッケージマネージャー)の採用も検討できます。詳細は以下の記事を参照してください:

ただし、Azure Functions では uv のロジックに直接対応していないため、本番デプロイ時には uvpiprequirements.txt への変換が必要です(コンテナだったら関係なかったかも…)。本記事では、標準的な pip + requirements.txt の構成を紹介します。

HTTP Trigger の作成と動作確認

HTTP Trigger 関数の作成

func new --name HttpExample --template "HTTP trigger" --authlevel "anonymous"

生成される内容:

  • function_app.py に HTTP Trigger 関数が追加されます

実装内容の確認

function_app.py:

import azure.functions as func
import datetime
import json
import logging

app = func.FunctionApp()


@app.route(route="HttpExample", auth_level=func.AuthLevel.ANONYMOUS)
def HttpExample(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    name = req.params.get('name')
    if not name:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            name = req_body.get('name')

    if name:
        return func.HttpResponse(f"Hello, {name}. This HTTP triggered function executed successfully.")
    else:
        return func.HttpResponse(
            "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.",
            status_code=200
        )

ポイント:

  • @app.route() デコレータでエンドポイントを定義
  • req.params.get('name') でクエリパラメータを取得
  • req.get_json() でリクエストボディを JSON として取得

ローカル実行

実行結果:

動作確認

別のターミナルで curl コマンドを実行:

curl "http://localhost:7071/api/HttpExample?name=Python"

期待される結果:

ブラウザでの確認:

  • http://localhost:7071/api/HttpExample にアクセス

Azurite と Timer Trigger

Timer Trigger を使うには、Azurite が必要です。詳細は Node.js 編 を参照してください。

Azurite の起動

DevContainer 内で、別のターミナルを開いて Azurite を起動します:

azurite --silent

# 設定やログを保存する先を指定
azurite --location .azurite --debug .azurite/debug.log

期待される結果:

Azurite Blob service is starting at http://127.0.0.1:10000
Azurite Blob service is successfully listening at http://127.0.0.1:10000
Azurite Queue service is starting at http://127.0.0.1:10001
Azurite Queue service is successfully listening at http://127.0.0.1:10001
Azurite Table service is starting at http://127.0.0.1:10002
Azurite Table service is successfully listening at http://127.0.0.1:10002

デフォルトポート:

  • Blob Service: 10000
  • Queue Service: 10001
  • Table Service: 10002

Timer Trigger 関数の作成

func new --name TimerExample --template "Timer trigger"

生成される内容:

  • function_app.py に Timer Trigger 関数が追加されます

実装内容の確認

function_app.py に追加される内容:

import azure.functions as func
import logging
import datetime

app = func.FunctionApp()

# (既存の HTTP Trigger はそのまま)

@app.timer_trigger(schedule="0 */5 * * * *", arg_name="myTimer", run_on_startup=False,
                   use_monitor=False)
def TimerExample(myTimer: func.TimerRequest) -> None:

    if myTimer.past_due:
        logging.info('The timer is past due!')

    logging.info('Python timer trigger function executed.')

ポイント:

  • @app.timer_trigger() デコレータで CRON 式を定義
  • myTimer.past_due で遅延実行を検知
  • CRON 式は UTC 時刻で動作(重要!)

ローカル実行

Azurite が起動している状態で、Functions を起動:

実行結果:

5 分ごとにログが表示されます。

トラブルシューティング(Python 固有)

Python 版で発生しやすいエラーと対処法です。

1. ModuleNotFoundError: No module named ‘azure’

症状:

  • func startModuleNotFoundError: No module named 'azure' エラー

対処法:

  • 仮想環境が有効になっているか確認
  • pip install -r requirements.txt を実行
  • 仮想環境の有効化:
  # Linux/macOS
  source .venv/bin/activate
  # Windows
  .venv\Scripts\Activate.ps1

2. Failed to start a new language worker for runtime: python

症状:

  • Failed to start a new language worker for runtime: python

対処法:

  • Python バージョンを確認(python --version
  • Azure Functions Core Tools が Python ワーカーをサポートしているか確認
  • 仮想環境を再作成:
  rm -rf .venv
  python -m venv .venv
  source .venv/bin/activate
  pip install -r requirements.txt

3. Azurite 接続エラー

症状:

  • No connection could be made because the target machine actively refused it

対処法:

  • Node.js 編のトラブルシューティングを参照
  • Azurite が起動しているか確認
  • local.settings.json の設定を確認

4. VSCode で Python インタープリタが見つからない

症状:

  • VSCode が Python を認識しない

対処法:

  • コマンドパレット(Ctrl+Shift+P)→「Python: Select Interpreter」
  • .venv/bin/python を選択

開発の推奨フロー

Python 版の開発フローです。

標準的な開発手順

  1. ターミナル 1: Azurite 起動
  1. ターミナル 2: 仮想環境の有効化と Functions 起動
   cd MyPythonFunctionApp

   # 仮想環境の有効化
   source .venv/bin/activate  # Linux/macOS
   # または
   .venv\Scripts\Activate.ps1  # Windows

   # Functions 起動
   func start
  1. 開発作業
  • function_app.py を編集
  • 保存すると自動的にリロード
  1. 動作確認
  • HTTP Trigger: curl やブラウザでアクセス
  • Timer Trigger: コンソールログで確認

Node.js 版との比較

項目 Node.js 版 Python 版
プロジェクト作成 func init --typescript func init --python
依存関係管理 npm / package.json pip / requirements.txt
メインファイル src/functions/*.ts function_app.py
仮想環境 不要(オプション) 推奨(.venv)
実行コマンド npm start func start
リロード watch mode(自動) ファイル変更検知(自動)

推奨 VSCode 拡張機能

DevContainer 内で自動的にインストールされる拡張機能:

  • Azure Functions (ms-azuretools.vscode-azurefunctions)
  • Python (ms-python.python)
  • Pylance (ms-python.vscode-pylance)
  • Black Formatter (ms-python.black-formatter)

まとめと次回予告

本記事で学んだこと

DevContainer を使った Python 版 Azure Functions 環境構築

  • Python 3.11 の DevContainer 構築
  • Dockerfile 方式を推奨(Python はバージョン依存が強いため)
  • Python Interpreter 設定の重要性
  • Python 仮想環境の作成と管理

Python での Azure Functions 開発

  • HTTP Trigger の作成と動作確認
  • Timer Trigger と Azurite の関係
  • function_app.py での関数定義

Python 固有のトラブルシューティング

  • 仮想環境のエラー対処
  • Python Worker プロセスエラー

Node.js 版と Python 版の使い分け

シナリオ 推奨言語 理由
単純な REST API どちらでも OK 要件による
データ分析・集計 Python pandas、NumPy が必須
機械学習推論 Python scikit-learn、TensorFlow
数値計算 Python SciPy、SymPy
スクレイピング Python BeautifulSoup
リアルタイム処理 Node.js async/await が得意
バッチ処理 どちらでも可 要件とチームのスキルセット次第

重要: 単純な REST API であれば、Node.js と Python のどちらでも問題ありません。特定のライブラリ(pandas、NumPy、scikit-learn など)が必要な場合のみ Python を選択してください!

次回の記事予告

次回は、Azure Functions 入門| HTTP Trigger と Timer Trigger の基礎と実践パターンを予定しています:

  • HTTP Trigger と Timer Trigger の詳細な使い方(Node.js 版)
  • 実践パターン: Timer Trigger を HTTP Trigger でデバッグする方法
  • タイムゾーン(UTC/JST)の扱い方
  • DRY 原則に基づいた共通ロジックの設計

サンプルリポジトリ

本記事で解説した環境を、すぐに試せるサンプルコードを公開しています:

  • GitHub: azure-functions-python-devcontainer
  • Python 3.11
  • HTTP Trigger + Timer Trigger 実装済み
  • DevContainer 設定ファイル完備
  • 仮想環境(.venv)セットアップ手順付き
  • クローンして VSCode で開くだけで動作します

関連記事

DevContainer を使った Python での Azure Functions 開発、ぜひ試してみてください!

データ分析や機械学習との組み合わせで、強力な自動化システムが構築できます。

次回もお楽しみに〜!


元の記事を確認する

関連記事