はじめに

Azure App ServiceへのアプリケーションデプロイにおいてCI/CD(継続的インテグレーション/継続的デリバリー)の導入は、開発の効率化と品質向上に不可欠です。
本記事では、GitHub Actionsを使用してAzure App Serviceへ自動デプロイする方法を解説します。

GitHub Actionsとは

GitHub Actionsは、GitHubが提供するCI/CD(継続的インテグレーション/継続的デリバリー)プラットフォームです。
リポジトリ内で直接ビルド、テスト、デプロイのワークフローを自動化できます。

特徴:

  • リポジトリと統合: GitHubリポジトリと密接に統合され、プッシュやプルリクエストなどのイベントに応じて自動実行
  • 豊富なアクション: GitHub Marketplaceで公開されている数千のアクションを活用可能
  • 無料枠: パブリックリポジトリは無料、プライベートリポジトリも一定時間まで無料

基本概念

ワークフロー(Workflow)

自動化されたプロセス全体を定義するYAMLファイル。.github/workflows/ディレクトリに配置します。

ジョブ(Job)

ワークフロー内で実行される作業の単位。複数のジョブを並行または順次実行できます。

ステップ(Step)

ジョブ内で実行される個別のタスク。コマンドの実行やアクションの呼び出しを行います。

アクション(Action)

再利用可能な処理単位。GitHub Marketplaceで公開されているものや、自作のものを使用できます。

ランナー(Runner)

ワークフローを実行する仮想マシン。GitHubホステッドまたはセルフホステッドを選択できます。

ワークフロー構文の基礎

基本的なワークフロー構文を見てみましょう:

name: 'ワークフロー名'

# トリガー条件
on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

# 環境変数
env:
  APP_NAME: my-app
  PYTHON_VERSION: '3.10'

# ジョブ定義
jobs:
  # ビルドジョブ
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - name: Setup Python
      uses: actions/setup-python@v5
      with:
        python-version: ${{ env.PYTHON_VERSION }}
    - name: Install dependencies
      run: pip install -r requirements.txt

主要な構文要素

  • name: ワークフローの名前
  • on: ワークフローをトリガーするイベント
  • env: 環境変数の定義
  • jobs: ジョブの定義
  • runs-on: ランナーの種類(ubuntu-latest、windows-latest、macos-latestなど)
  • steps: 実行するステップのリスト
  • uses: 使用するアクション
  • run: 実行するコマンド
  • with: アクションへのパラメータ

詳細はワークフロー構文の公式ドキュメントを参照してください。

実践例:Azure App Serviceへのデプロイ

PythonアプリをAzure App Serviceにデプロイする実践的なワークフローを見てみましょう。

全体構成

name: '[Production] Build and deploy Python app to Azure Web App'

on:
  push:
    branches:
      - main

env:
  AZURE_WEBAPP_NAME: app-test-dev-001
  AZURE_WEBAPP_SLOT_NAME: staging
  AZURE_WEBAPP_PACKAGE_PATH: '.'
  PYTHON_VERSION: '3.10'
  PYTHON_MAJOR_VERSION: '3'
  STARTUP_COMMAND: 'python3 -m gunicorn main:app'
  BUILD_ARTIFACT_NAME: build-artifact
  BUILD_ZIP_FILE_NAME: build.zip

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    # リポジトリのチェックアウト
    - uses: actions/checkout@v4

    # Pythonのセットアップ
    - name: Setup Python
      uses: actions/setup-python@v5
      with:
        python-version: ${{ env.PYTHON_VERSION }}

    # 依存関係のインストール
    - name: python install
      working-directory: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
      run: |
        sudo apt install python${{ env.PYTHON_MAJOR_VERSION }}-venv
        python -m venv --copies antenv
        source antenv/bin/activate
        pip install setuptools
        pip install -r requirements.txt        

    # ビルド成果物のZIP化
    - name: Archive build zip
      run: |
                zip -qr ${{ env.BUILD_ZIP_FILE_NAME }} ./* -x '*.git*'

    # 成果物のアップロード
    - name: Upload artifact for deployment job
      uses: actions/upload-artifact@v4
      with:
        name: ${{ env.BUILD_ARTIFACT_NAME }}
        path: ${{ env.BUILD_ZIP_FILE_NAME }}

  deploy:
    name: Deploy
    runs-on: ubuntu-latest
    environment: prd
    if: ${{ (!cancelled() && !failure()) }}
    needs: build
    steps:
    # Azure ログイン
    - uses: azure/login@v2
      with:
        creds: ${{ secrets.AZURE_CREDENTIALS }}

    # ビルド成果物のダウンロード
    - name: Download artifact from build job
      uses: actions/download-artifact@v4
      with:
        name: ${{ env.BUILD_ARTIFACT_NAME }}

    # Web Appへのデプロイ
    - name: deploy web app
      uses: azure/webapps-deploy@v3
      with:
        app-name: ${{ env.AZURE_WEBAPP_NAME }}
        package: ${{ env.BUILD_ZIP_FILE_NAME }}
        clean: true
        type: zip
        restart: false
        startup-command: ${{ env.STARTUP_COMMAND }}
        slot-name: ${{ env.AZURE_WEBAPP_SLOT_NAME }}

    # App Serviceの設定
    - name: setting app setting
      uses: azure/appservice-settings@v1
      with:
        app-name: ${{ env.AZURE_WEBAPP_NAME }}
        slot-name: ${{ env.AZURE_WEBAPP_SLOT_NAME }}
        mask-inputs: false
        general-settings-json: '{"linuxFxVersion": "PYTHON|${{ env.PYTHON_VERSION }}"}'
        app-settings-json: |
          [
              {
                  "name": "HOGEHOGE",
                  "value": "${{ secrets.HOGEHOGE }}",
                  "slotSetting": false
              }
          ]          

    # Azure ログアウト
    - name: logout
      run: |
                az logout

ワークフローのポイント

1. ジョブの依存関係

needs: build

deployジョブはbuildジョブの完了後に実行されます。

2. 成果物の受け渡し

upload-artifactdownload-artifactを使用して、ビルドジョブとデプロイジョブ間でファイルを受け渡します。

3. シークレットの使用

creds: ${{ secrets.AZURE_CREDENTIALS }}

機密情報はGitHubのSecretsに保存し、${{ secrets.変数名 }}で参照します。

4. 条件付き実行

if: ${{ (!cancelled() && !failure()) }}

前のジョブが失敗またはキャンセルされていない場合のみ実行します。

Azure App Serviceのビルドとデプロイ方法

Azure App Serviceへのデプロイには複数の方法があります。プロジェクトの要件に応じて最適な方法を選択しましょう。

注意: サンプルワークフローは内容が古いものが多いため、最新の公式ドキュメントで確認することを推奨します。

1. ZIPデプロイ

ビルド済みの成果物をZIPファイルとしてパッケージし、Azure App Serviceにアップロードする方法です。

メリット:

  • シンプルで理解しやすい
  • ビルド環境を完全にコントロール可能
  • デプロイが高速
  • 成果物の内容を事前に確認できる

使用例: 本記事で紹介しているワークフローサンプル

2. Gitデプロイ

ソースコードリポジトリとAzure App Serviceを連携させ、リポジトリにコミットがプッシュされるたびに、自動的にビルドとデプロイを行う方法です。

メリット:

  • セットアップが簡単
  • App Service側で自動的にビルドされる
  • デプロイ履歴がGitの履歴と連動

デメリット:

  • ビルド環境のコントロールが制限される
  • ビルド時間がApp Serviceのリソースに依存

3. ローカルビルド

App Service上のビルド環境ではなく、PCやGitHub Actionsなどのローカル環境でビルドを行う方法です。

設定:

- name: setting app setting
  uses: azure/appservice-settings@v1
  with:
    app-name: ${{ env.AZURE_WEBAPP_NAME }}
    slot-name: ${{ env.AZURE_WEBAPP_SLOT_NAME }}
    app-settings-json: |
      [
          {
              "name": "SCM_DO_BUILD_DURING_DEPLOYMENT",
              "value": "false",
              "slotSetting": false
          }
      ]      

メリット:

  • ビルド環境を完全にコントロール可能
  • ビルドツールのバージョンを固定できる
  • デバッグが容易

推奨: GitHub Actionsでビルドする場合はSCM_DO_BUILD_DURING_DEPLOYMENT=falseを設定し、二重ビルドを回避します。

4. リモートビルド

App ServiceのSCM(Source Control Management)サイト上でビルドを行う方法です。WindowsではKudu、LinuxではOryxを用いたビルドが実行されます。

トリガー条件:

  • ローカルGitデプロイでApp Service上のgitリポジトリへpushした場合
  • .deploymentファイルでSCM_DO_BUILD_DURING_DEPLOYMENT=trueを指定した場合
  • アプリケーション設定でSCM_DO_BUILD_DURING_DEPLOYMENT=trueを設定した場合

設定:

- name: setting app setting
  uses: azure/appservice-settings@v1
  with:
    app-name: ${{ env.AZURE_WEBAPP_NAME }}
    slot-name: ${{ env.AZURE_WEBAPP_SLOT_NAME }}
    app-settings-json: |
      [
          {
              "name": "SCM_DO_BUILD_DURING_DEPLOYMENT",
              "value": "true",
              "slotSetting": false
          }
      ]      

ビルドプロセス:

  1. ソースコードがApp Serviceにデプロイされる
  2. KuduまたはOryxがビルドを実行
  3. ビルド成果物(コンパイル済みコード、ライブラリ等)が生成される
  4. 成果物は一般的に圧縮形式(例: output.tar.gz)でパッケージされる

重要な注意点:

  • SCM_DO_BUILD_DURING_DEPLOYMENT=trueの場合、ZIPデプロイでもGitデプロイと同様に自動ビルドが実行されます
  • GitHub Actionsでビルドを行い、さらにリモートビルドも有効にすると、ビルドが2回実行されるため非効率です
  • GitHub Actionsを使用する場合はSCM_DO_BUILD_DURING_DEPLOYMENT=falseを強く推奨

ビルド方法の選択ガイド

デプロイ方法 ビルド場所 SCM_DO_BUILD_DURING_DEPLOYMENT 推奨ケース
ZIPデプロイ + ローカルビルド GitHub Actions false CI/CD環境がある場合(推奨)
ZIPデプロイ + リモートビルド App Service true CI/CD環境がない場合
Gitデプロイ App Service true(自動) 小規模プロジェクト、シンプルな構成

よくあるエラーと対処法

1. RBAC認証でのデプロイエラー

エラーメッセージ:

Error: When request Azure resource at PublishContent, Sync Trigger Functionapp :
Failed to perform sync trigger on function app. Function app may have malformed content.

原因: Ubuntu(Linux)ランナーでRBAC認証を使用する際の既知の問題

対処法:

  • Stackoverflowを参照
  • 必要に応じてサービスプリンシパル認証に切り替え

2. 仮想環境が見つからないエラー

エラーメッセージ:

Could not find virtual environment directory /home/site/wwwroot/antenv

対処法: Python仮想環境を正しく作成し、パッケージに含めます:

- name: python install
  run: |
    python -m venv --copies antenv
    source antenv/bin/activate
    pip install -r requirements.txt    

参考: GitHub Actions Azure App Service Workflow Sample

3. 既存ファイルが削除されない

症状: デプロイ後も古いファイルがApp Service上に残る

対処法: cleanオプションをtrueに設定

- name: deploy web app
  uses: azure/webapps-deploy@v3
  with:
    app-name: ${{ env.AZURE_WEBAPP_NAME }}
    package: ${{ env.BUILD_ZIP_FILE_NAME }}
    clean: true
    type: zip
    restart: false

参考:

OIDCによる安全な認証

従来のサービスプリンシパル認証に代わり、OpenID Connect(OIDC)を使用することで、シークレットを管理せずにAzureに安全に接続できます。

メリット:

  • クレデンシャルのローテーション不要
  • より安全な認証
  • 短命なトークンの使用

参考: GitHub Actions で OpenID Connect(OIDC) で Azure に安全に接続する

主要なGitHub Actionsアクション

Azure関連

Azure WebApp

Azure App ServiceへのWebアプリケーションデプロイに使用します。

Azure App Service Settings

App Serviceのアプリケーション設定や一般設定を構成します。

注意: Azure DevOpsのパイプラインタスクと同様の機能をGitHub Actionsで利用できます。

標準アクション

参考リソース

公式ドキュメント

GitHub Actions

Azure App Service

Azure DevOps

サンプルリポジトリとアクション定義

注意: サンプルは内容が古いものが多いため、最新の公式ドキュメントで確認することを推奨します。

GitHub Marketplace

コミュニティ記事

App Serviceデプロイとビルド

トラブルシューティング

まとめ

GitHub Actionsは、強力で柔軟なCI/CDプラットフォームです。Azure App Serviceへのデプロイを例に見てきましたが、他のクラウドサービスやさまざまな自動化タスクにも応用できます。

重要なポイント:

  1. ワークフロー構文を理解する
  2. ジョブの依存関係を適切に設定
  3. シークレットを安全に管理
  4. ビルド方法(ローカル/リモート)を適切に選択
  5. SCM_DO_BUILD_DURING_DEPLOYMENTの設定に注意

まずは小さなワークフローから始めて、徐々に複雑なパイプラインを構築していくことをお勧めします。