3
2

More than 1 year has passed since last update.

BicepとAzure DevOpsを使ったAzure Static Web AppsへのReactのサンプルアプリのデプロイ

Posted at

はじめに

ARM(Azure Resource Manager)テンプレートの存在は以前から知っていたのですが、最近になってARMテンプレートをさらに見やすく・扱いやすくしたBicepの存在を知りました。Bicepは最近アツくなってきているらしく、興味を持ったので勉強したことを本記事にまとめたいと思います。本記事の内容がより実用的な内容になるように、Bicepを使ってAzureリソースをデプロイするだけではなく、ReactのサンプルWebアプリをAzure DevOpsを使って自動デプロイするところまでまとめました。

アーキテクチャ

本記事で構築するアーキテクチャは以下の図になります。
image.png

Azure Static Web Appsとは

本記事のメインであるBicepを紹介する前に、Azure Static Web Appsとは何かについて先に説明をしたいと思います。Azure Static Web AppsSPA(Single Page Application)用のAzureリソースであり、静的サイトホスティング環境です。Angular、React、Svelte、Vue、Blazor など、サーバー側のレンダリングが不要なライブラリとWebフレームワークを使用することができます。GitHubやAzure DevOpsとの連携が容易であり、簡単な設定によりCI/CDを組むことが可能です。
image.png
Azure Static Web Apps自体は静的Webアプリのホスティングサービスですが、Azure Functionsと組み合わせることで簡単に動的Webアプリを構築することも可能です。Azure Static Web AppsAzure Functionsを組み合わせて動的なWebアプリを作りたい方は、以下の記事をご覧ください。

Bicepとは

本記事のメインコンテンツであるBicepについて説明したいと思います。Bicepとは、Azureリソースをデプロイするための、宣言型構文のドメイン固有言語(DSL)です。 要するに、Azure用のコードとしてのインフラストラクチャ(IaC: Infrastructure as Code)になります。

コードとしてのインフラストラクチャ(IaC)とは?
ネットワーク、仮想マシン、ロードバランサー、接続トポロジ、DevOpsの手法とバージョン管理などのインフラストラクチャを定義してデプロイするためのコードであり、デプロイするたびに同じ環境を生成します。
https://learn.microsoft.com/ja-jp/devops/deliver/what-is-infrastructure-as-code

BicepとARMテンプレートの違い

Bicepと似たものとして、ARMテンプレートがあります。ARMテンプレートとは、プロジェクトのインフラストラクチャと構成が定義されているJSONファイルです。ARMテンプレートのJSONは冗長になることがありますが、Bicepではその複雑さが軽減されます。同じストレージアカウントをデプロイするためのBicepファイルとARMテンプレートを以下の実際のコードで比較しましょう。

Bicep
param location string = resourceGroup().location
param storageAccountName string = 'toylaunch${uniqueString(resourceGroup().id)}'

resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' = {
  name: storageAccountName
  location: location
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'StorageV2'
  properties: {
    accessTier: 'Hot'
  }
}
JSON
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    },
    "storageAccountName": {
      "type": "string",
      "defaultValue": "[format('toylaunch{0}', uniqueString(resourceGroup().id))]"
    }
  },
  "resources": [
    {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2021-06-01",
      "name": "[parameters('storageAccountName')]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard_LRS"
      },
      "kind": "StorageV2",
      "properties": {
        "accessTier": "Hot"
      }
    }
  ]
}

Bicepファイルの方がARMテンプレートよりも、簡潔にインフラ構成を記述できていることが確認できたと思います。

Bicepでは同等のJSONと比較して、より簡単で簡潔な構文を提供できるため、MicrosoftはARMテンプレートよりも、改良版言語であるBicepの使用を推奨しています。

BicepとARMテンプレートの関係性

BicepをコンパイルするとARMテンプレートになり、ARMテンプレートをデコンパイルするとBicepになります。この関係性を図式化すると以下になります。
image.png

IaCと非テンプレートIaCの違い

Azureのリソースを作成するために例えば、以下のようにAzure CLIを使うことも可能です。

Azure CLI
az staticwebapp create \
    --name my-first-static-web-app \
    --resource-group my-swa-group \
    --source https://github.com/$GITHUB_USER_NAME/my-first-static-web-app \
    --location "eastus2" \
    --branch main \
    --app-location "src" \
    --login-with-github

Azure CLIでの命令をシェルスクリプト化(非テンプレートIaC)して手続き的にリソースをデプロイすることも可能ですが、通常のIaCを使用する方が様々な理由からメリットが大きいです。そのうちの1つの理由として挙げられるのが、通常のIaCであれば命令コマンドの回数を1回で済ませられることです。下の図では、IaC(図ではARMテンプレート)と非テンプレートIaCの命令コマンドの回数違いが示されています。
image.png
ARMテンプレートのようなIaCでは、相互に依存するリソースのデプロイが調整され、正しい順序で作成されるので複雑な順序付けのことを心配する必要はなく、1つの命令コマンドでデプロイは完了する並列デプロイになります。一方で非テンプレートIaCでは、順番を考慮した上で複数の命令コマンドを行う必要性があるため、直列デプロイになります。並列デプロイは直列デプロイに比べ、短時間でデプロイが完了する点でも優れているデプロイ方法になります。

Bicepファイルの作成方法

ここでは、VSCodeを使ってBicepファイルを作成する方法を紹介します。

Bicepの拡張機能をインストール

まずはVSCodeにBicep拡張機能をインストールしましょう。
image.png

Bicep拡張機能の機能

Bicepの拡張機能には主に以下のような機能があります。Bicepファイルの作成においては、スニペットが特に強力な機能になります。

  • バリデーション
  • スニペット
  • コードナビゲーション
    • 定義
    • 定義のピーク
  • ハイライト
  • リファクター
  • フォーマッティング

リソースの作成

Bicep拡張機能をインストールしたら、VSCodeで任意のファイル名のBicepファイルを展開してください。そこで、作成したいリソースを入力してください。以下のスクリーンショットの例では、storageと入力しました。するとリストが表示されるので、res-storageを選択してEnterキーを入力しました。
image.png
すると、一瞬で次のコードが追加されます。このように、Bicep拡張機能のスニペット機能を使用することで、一瞬で作成したいリソースを含むBicepファイルが作成できました。
image.png

今回紹介したBicep拡張機能のスニペット機能は強力ですが、全てのリソースに対応しているわけではありません。Azure Static Web Appsのように登録されていないソースコードは公式ドキュメントを参照して確認しましょう。今回はこちらの記事でまとめられているAzure Static Web AppsのBicepテンプレートを参考にしました。

Bicepファイルの作成について、詳しくは以下の公式ドキュメントが参考になります。

サンプルアプリをデプロイして実行するまでの流れ

ここから、次の流れでサンプルアプリをAzure上で実行するところまでの手順をまとめたいと思います。

  1. アプリ開発
  2. ローカルでの実行
  3. Azureリソースのデプロイ
  4. アプリのデプロイ
  5. クラウドでの実行

1. アプリ開発

まず最初の工程としてWebアプリを開発しましょう。アプリ開発は本記事の目的ではないため、以下のリポジトリに保存されているReactのWebアプリを使用させていただきました。このWebアプリは、絵文字検索ができるアプリになります。

2. ローカルでの実行

先ほどご紹介したサンプルアプリをローカルで実行するために、お好きなシェルを開いてnpm startを実行します。その後、ブラウザでhttp://localhost:3000にアクセスすれば以下のスクリーンショットのような画面が表示されます。
image.png
このようにローカルでは、適切にアプリが動くことが確認できました。

3. Azureリソースのデプロイ

ローカルで動いているWebアプリをデプロイするために、Azureリソースのデプロイを事前に行いましょう。

Bicepファイルの作成

本記事のタイトルに含まれているBicepをここから使っていきます。Bicepを使うことで、簡単にAzureリソースのデプロイを行うことができます。今回は以下のBicepファイルを使用しました。repositoryUrlは適宜自分のリポジトリを指定してください。

main.bicep
param appName string = 'bicep-practice-app'
param location string = 'eastasia'
param skuName string = 'Free'
param skuTier string = 'Free'
param provider string = 'DevOps'
param repositoryUrl string = 'https://github.com/yus04/React-emoji-search'
param branch string = 'main'

resource staticWebApp 'Microsoft.Web/staticSites@2022-03-01' = {
  name: appName
  location: location
  sku: {
    name: skuName
    tier: skuTier
  }
  properties: {
    provider: provider
    repositoryUrl: repositoryUrl
    branch: branch
  }
}

リソースグループの作成

Azureポータルから任意のリソースグループ名、リージョンでリソースグループを作成します。
image.png

Azure Static Web Appsのデプロイ

先ほど作成したリソースグループの中で、BicepとAzure CLIを使用してAzure Static Web Appsをデプロイします。"provisioningState": "Succeeded"と返ってきたらデプロイは成功です。

Azure CLI
az deployment group create \
  --name ExampleDeployment \
  --resource-group ExampleGroup \
  --template-file <path-to-bicep> \

Bicepファイルをデプロイするときに、--nameでデプロイに名前を付けることができます。

BicepとAzure CLIを使用したリソースのデプロイについては、以下の記事が参考になります。

Azureポータルを開き、静的Webアプリが作られていることが確認できます。次のスクリーンショットの赤枠で囲まれた部分がWebアプリのURLになっているので、コピーしてブラウザでアクセスしてみましょう。
image.png
ブラウザで次のような画面が表示されれば、Azure Static Web Appsのデプロイは成功です。
image.png

4. アプリのデプロイ

次はローカルで動いているWebアプリをAzure Static Web Appsにデプロイしていきましょう。本記事ではAzure DevOpsを使って、WebアプリのソースコードをGitHubリポジトリのmainブランチへプッシュした時に自動ビルド&自動デプロイするCI/CD環境を構築します。

パイプラインの定義

Azure DevOpsのPipelinesを使います。以下のazure-pipelines.yamlファイルを使用しました。

azure-pipelines.yaml
trigger:
  - main
pool:
  vmImage: ubuntu-latest
steps:
  - task: AzureStaticWebApp@0
    name: DeployStaticWebApp
    displayName: Deploy Static Web App
    inputs:
      app_location: /
      output_location: build
    env:
      azure_static_web_apps_api_token: $(deployment_token)

yamlファイルのsteps.taskで使用されているAzureStaticWebApp@0Azure Static Web Appsアプリをビルド&デプロイするタスクになります。このタスクについては以下の公式ドキュメントで詳しく説明されています。

パッケージファイルの準備

以下のjsonファイルを使用しました。

package.json
{
  "name": "emoji-search",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.11.10",
    "@testing-library/react": "^11.2.6",
    "@testing-library/user-event": "^12.8.3",
    "react": "^17.0.2",
    "react-copy-to-clipboard": "^5.0.3",
    "react-dom": "^17.0.2",
    "web-vitals": "^1.1.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "prettier": "^2.2.1",
    "react-scripts": "^4.0.3"
  }
}

先ほどのazure-pipelines.yamlsteps.taskに記述されているAzureStaticWebApp@0が実行されることで、scripts.buildに記述されているreact-scripts buildが実行されます。

GitHubリポジトリの作成

GitHubリポジトリを作成し、ソースコードをプッシュします。main.bicepazure-pipelines.yamlを作成し、最終的なフォルダ構成は以下になりました。

フォルダ構成
.
├─ build
│  └─ ...
├─ node_modules
│  └─ ...
├─ public
│  └ ...
├─ src
│  └ ...
├─ .gitignore
├─ azure-pipelines.yaml
├─ main.bicep
├─ package-lock.json
├─ package.json
└─ README.md

それぞれのディレクトリやファイルの解説は次の通りになります。

  • build/
    • npm run buildを実行したときに生成される本番向けのビルド済みアプリを格納するディレクトリ
  • node_modules/
    • Node.jsで使用するパッケージをインストールするディレクトリ
    • package.jsonに記述されたパッケージ名とバージョンを元に、npm installコマンドでインストールされる
  • public/
    • 公開される静的ファイルを格納するディレクトリ
  • src/
    • アプリケーションのソースコードを格納するディレクトリ
  • .gitignore
    • Gitで管理するファイルのうち、バージョン管理しないファイルを指定するためのファイル
  • azure-pipelines.yaml
    • Azure Pipelinesでビルドやデプロイを行うための設定ファイル
  • main.bicep
    • Azureリソースを定義するためのBicepファイル
  • package-lock.json
    • node_modules/の構造やpackage.jsonが修正または生成される際の依存性を正確かつ具体的な情報を記載するファイル
    • npm installコマンドでインストールされたパッケージのバージョンを固定するために使用
  • package.json
    • Node.jsにおいてインストールするパッケージが記述されたJSONファイル
    • パッケージ管理の設計書なので、異なる環境でも読み込むことで同じパッケージをインストール可能
  • README.md
    • プロジェクトの説明や使い方などが記述されたファイル

build及びnode_modulesフォルダとその中身、およびpackage-lock.jsonフォルダをリポジトリに保存したくないため、以下の通りに.gitignoreファイルに記載しました。

.gitignore
build/
node_modules/
package-lock.json

パイプラインの作成

次に、GitHubリポジトリに保存されているazure-pipelines.yamlを使って、Azure DevOpsのPipelinesを作成します。まず、Azure DevOpsのPipelines画面を開いて、「Create Pipeline」を押します。
image.png
ソースコードの保存元として「GitHub」を選択します。
image.png
リポジトリを選択します。
image.png
GitHubに保存されているazure-pipelines.yamlを使ってパイプラインを定義したいので、「Existing Azure Pipelines YAML file」を選択します。
image.png
ブランチを指定した後で、パスとして「/azure-pipelines.yaml」を選択します。
image.png
以上で、パイプラインの作成ができました。

環境変数の登録

azure-pipelines.yamlenvで使われている環境変数deployment_tokenの設定をAzure DevOpsで行います。まず、次のスクリーンショットの通りに「Edit」を選択します。
image.png
「Variables」を選択します。
image.png
「New Variable」を選択します。
image.png
Nameをdeployment_token、ValueをAzureポータルでコピーしたデプロイトークンにします。デプロイトークンの取得方法は次に紹介します。NameとValueを入力と「Keep this value secret」のチェックをしたら「OK」ボタンを押下します。
image.png

デプロイトークンの取得

Azureポータルを開いて、Bicepでデプロイ済みの静的Webアプリの概要画面を開きます。次のスクリーンショットの赤枠で囲まれている「デプロイトークンの管理」を押下します。
image.png
すると、デプロイトークンが表示されるので右のアイコンを押下してクリップボードにコピーすることで、デプロイトークンを取得できます。
image.png

アプリのビルドとデプロイの実行

以上でアプリのデプロイの準備が完了しました。アプリのビルドとデプロイを行っていきましょう。Pipelinesの画面右上にある、「Run pipeline」を押します。
image.png
「Run」を押します。
image.png
Pipelinesの画面では、パイプラインで定義したタスクが実行されているのをリアルタイムで確認することができます。次のスクリーンショットのように、Jobに緑色のチェックマークがつけば、エラーなくアプリのビルドとデプロイが完了したことを意味しています。
image.png

5. クラウドでの実行

AzureポータルのAzure Static Web Appsの概要画面に表示されているURLにブラウザでアクセスしてみて、次のスクリーンショットのような画面が表示されれば、無事にReactのサンプルアプリがAzure Static Web Appsにデプロイできました。
image.png

不要になったリソースは、Azure CLIを使ってリソースグループごとクリーンアップしましょう。

Azure CLI
az group delete --name exampleRG

おわりに

BicepとAzure DevOpsを使って簡単にAzure Static Web AppsにReactのサンプルアプリをデプロイすることができました。もちろん、Azureポータルを使ってリソースを作成することは簡単なのですが、VSCodeのBicep拡張機能を使うことで簡単にBicepファイルを作成することができるため、Bicepによるリソース作成も容易であることに感動しました。初めはとっつきにくかったBicepでしたが、今後は積極的に利用していきたいと思います。

3
2
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
3
2