📑

Azure App Serviceのデプロイスロットを試す

2024/08/20に公開

PoetryによるDjangoアプリケーションのAzure App Serviceテスト手順(完全版)

1. 環境準備

1.1 Poetryのインストール(まだの場合)

curl -sSL https://install.python-poetry.org | python3 -

1.2 プロジェクトの初期化

mkdir django-azure-project
cd django-azure-project
poetry init -n

1.3 必要なパッケージのインストール

poetry add django gunicorn
poetry add --dev pylint djangorestframework

ここで仮想環境を有効にしておくとエディタでインポートエラーが出ないのでやっておく
https://zenn.dev/ytksato/articles/33e4d9a03fd660

1.4 Djangoプロジェクトの作成

poetry run django-admin startproject myproject .
poetry run python manage.py startapp myapp

1.5 基本的な設定

myproject/settings.py を編集:

ALLOWED_HOSTS = ['*']  # 本番環境では適切に設定すること
INSTALLED_APPS = [
    # ...
    'myapp',
]

1.6 サンプルビューの作成

myapp/views.py を編集:

from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, Azure!")

myproject/urls.py を編集:

from django.urls import path
from myapp import views

urlpatterns = [
    path('', views.index, name='index'),
]

1.7 Gitリポジトリの初期化

git init
echo ".venv/" > .gitignore
echo "*.pyc" >> .gitignore
echo "__pycache__/" >> .gitignore
git add .
git commit -m "Initial Django project with Poetry"

1.8 GitHubリポジトリの作成と連携

  1. GitHubで新しいリポジトリを作成(ブラウザからアクセスして新規作成する)
  2. ローカルリポジトリをプッシュ:
git remote add origin https://github.com/yourusername/your-repo-name.git
git branch -M main # 最初からmainならいらない
git push -u origin main

2. Azure App Service準備

2.1 Azure CLIでのリソース作成

# リソースグループの作成
az group create --name myResourceGroup --location eastus

# App Serviceプランの作成
az appservice plan create \
    --name myAppServicePlan \
    --resource-group myResourceGroup \
    --sku P0V3 \
    --is-linux

# Webアプリの作成
az webapp create --resource-group myResourceGroup --plan myAppServicePlan --name your-app-name --runtime "PYTHON|3.9" --deployment-local-git

# デプロイメントスロットの作成
az webapp deployment slot create --name your-app-name --resource-group myResourceGroup --slot staging

2.2 デプロイメント設定

# デプロイメント資格情報の設定
az webapp deployment user set --user-name <username> --password <password>

# GitリモートURLの取得
az webapp deployment source config-local-git --name your-app-name --resource-group myResourceGroup --slot staging

3. Azure用の設定調整

3.1 requirements.txtの生成

poetry export -f requirements.txt --output requirements.txt --without-hashes --only main

3.2 Gunicorn設定ファイルの作成

gunicorn.conf.py をプロジェクトルートに作成:

# gunicorn.conf.py
workers = 4
bind = "0.0.0.0:8000"
module = "myproject.wsgi:application"

3.3 Azure用のstartup commandの設定

Azure Portalで、App Serviceの「設定」→「構成」→「全般設定」で以下のStartup Commandを設定:

gunicorn --config gunicorn.conf.py myproject.wsgi

4. CI/CD設定

4.1 GitHub Actionsワークフローの作成

.github/workflows/azure-deploy.yml ファイルを作成:

name: Build and deploy Python app to Azure Web App

on:
  push:
    branches:
      - main
  workflow_dispatch:

permissions:
  id-token: write
  contents: read

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Set up Python version
        uses: actions/setup-python@v5
        with:
          python-version: '3.10'  # 必要に応じてバージョンを変更
      
      - name: Install Poetry
        run: |
          curl -sSL https://install.python-poetry.org | python3 -
          echo "$HOME/.local/bin" >> $GITHUB_PATH
      
      - name: Install dependencies
        run: |
          poetry install
      
      - name: Run tests
        run: |
          poetry run python manage.py test
      
      - name: Set up environment variables
        run: |
          echo "DJANGO_SETTINGS_MODULE=your_project.settings" >> $GITHUB_ENV  # プロジェクト名を変更
          echo "STATIC_ROOT=/tmp/staticfiles" >> $GITHUB_ENV
      
      - name: Collect static files
        run: |
          mkdir -p $STATIC_ROOT
          poetry run python manage.py collectstatic --noinput
      
      - name: Create requirements.txt
        run: |
          poetry export -f requirements.txt --output requirements.txt --without-hashes
      
      - name: Zip artifact for deployment
        run: zip release.zip ./* -r
      
      - name: Upload artifact for deployment jobs
        uses: actions/upload-artifact@v4
        with:
          name: python-app
          path: |
            release.zip
            !venv/

  deploy:
    runs-on: ubuntu-latest
    needs: build
    environment:
      name: 'staging'  # 必要に応じて環境名を変更
      url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}
    
    steps:
      - name: Download artifact from build job
        uses: actions/download-artifact@v4
        with:
          name: python-app
      
      - name: Unzip artifact for deployment
        run: unzip release.zip
      
      - name: Login to Azure
        uses: azure/login@v2
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
      
      - name: 'Deploy to Azure Web App'
        uses: azure/webapps-deploy@v3
        id: deploy-to-webapp
        with:
          app-name: 'your-app-name'  # Azure Web Appの名前に変更
          slot-name: 'staging'  # 必要に応じてスロット名を変更

GitHub SecretsにAzure Web App公開プロファイルを追加。

4.2 初回デプロイ

git add .github/workflows/azure-deploy.yml gunicorn.conf.py requirements.txt
git commit -m "Add deployment configuration"
git push origin main

ここでAzure認証で大ハマリした。
先に以下の内容を設定しておかないとgithub actions内でのAzure認証がうまくいかない。
https://zenn.dev/dzeyelid/articles/5f20acbe549666

GitHub ActionsからOIDCでAzureのリソースに安全に接続する手順

  1. Microsoft Entra IDで作成したアプリケーションを登録する
  2. 作成したMicrosoft Entra IDアプリケーションにフェデレーション資格情報を追加する
  3. Azureで認可させたいリソースにロールを割り当てる
  4. GitHub Actionsのシークレットに、下記を設定する
  5. Microsoft Entra IDアプリケーションのクライアントID, AzureのテナントID, AzureのサブスクリプションID
  6. GitHub Actionsワークフローで Azure/login アクションでログインする

上記参考にした記事と違う所

  • uses: azure/login@v1 → uses: azure/login@v2でバージョンが違う
  • githubの設定にenvironmentが無い(無いけどフェデレーション資格情報は「環境」を選択してうまく行った謎が残る)
  • リソースグループにロールの割当をする時にメンバーを選択する画面でリストにアプリが無いが検索すると出てくる(ハマりポイント)

5. IPアドレス制限とテスト

5.1 Azure PortalでのIP制限設定

  1. Azure Portalにログイン
  2. 該当のApp Serviceリソースに移動
  3. 左側メニューから「ネットワーク」を選択
  4. 「受信トラフィック」セクションで「アクセス制限」を選択
  5. 「追加」ボタンをクリック
  6. 以下の情報を入力:
    • 名前: 任意の名前(例: "AllowedIP1")
    • アクション: 許可
    • 優先度: 数値(低いほど優先)
    • IPアドレス: 許可するIPアドレスまたは範囲
  7. 「追加」をクリックして保存

5.2 IPアドレス制限のテスト

  1. 許可したIPアドレスからアプリケーションにアクセス
    • 正常にアクセスできることを確認
  2. 許可していないIPアドレスからアクセス
    • アクセスが拒否されることを確認
  3. 複数のIPアドレス/範囲でテスト
    • 必要に応じて複数のIPを追加し、それぞれでアクセスをテスト

5.3 スロット間のIP制限テスト

  1. プロダクションスロットとステージングスロットで異なるIP制限を設定
  2. 各スロットで設定したIPからのアクセスをテスト
  3. スロットをスワップし、IP制限が正しく機能するか確認

6. モニタリングとログ

6.1 Application Insightsの設定

  1. Azure Portalで新しいApplication Insightsリソースを作成
  2. 作成したApplication InsightsのInstrumentation Keyをコピー
  3. App Serviceの「設定」→「構成」→「アプリケーション設定」で新しい設定を追加:
    • 名前: APPINSIGHTS_INSTRUMENTATIONKEY
    • 値: コピーしたInstrumentation Key

6.2 Djangoでのログ設定

myproject/settings.py を編集:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
        },
    },
    'root': {
        'handlers': ['console'],
        'level': 'INFO',
    },
}

6.3 アプリケーションにログを追加

myapp/views.py にログを追加:

import logging

logger = logging.getLogger(__name__)

def index(request):
    logger.info("Index page was accessed")
    return HttpResponse("Hello, Azure!")

6.4 変更のデプロイ

git add myproject/settings.py myapp/views.py
git commit -m "Add logging configuration"
git push origin main

6.5 ログの確認

  1. Azure Portalで App Serviceリソースの「監視」→「ログストリーム」を確認
  2. Application Insightsでログとテレメトリを確認

7. 最終確認とクリーンアップ

7.1 全体的な動作確認

  1. アプリケーションの機能が正しく動作しているか確認
  2. IP制限が期待通りに機能しているか確認
  3. ログが正しく記録されているか確認

7.2 パフォーマンステスト

  1. 負荷テストツールを使用してアプリケーションのパフォーマンスを測定
  2. Application Insightsでパフォーマンスメトリクスを確認

7.3 セキュリティ確認

  1. SSL/TLS設定が正しく機能しているか確認
  2. 不要な
    ポートやエンドポイントが公開されていないか確認

7.4 クリーンアップ(必要な場合)

  1. テスト用に作成したリソースを削除
az group delete --name myResourceGroup --yes --no-wait
  1. ローカル環境のクリーンアップ
# 仮想環境の削除(オプション)
poetry env remove python

この手順書に従うことで、Poetryを使用したDjangoアプリケーションのAzure App Serviceへのデプロイとテストを包括的に実行できます。
各ステップで問題が発生した場合は、エラーメッセージを確認し、必要に応じて Azure のドキュメントを参照してください。

Discussion