Azure App ServiceでLaravelアプリを公開する

# はじめに
今回は`Azure App Service`を使って`Laravel`アプリを公開しようと思います。先日投稿した記事では、`Azure Static Web Apps`を使ってWebアプリを立ち上げました。

https://qiita.com/y__saito/items/7c78893eaf2af6ecd301

`Azure`あるあるだと思いますが、サービスが多すぎたり、似通ったサービスがあったりして、何のサービスを使うべきなのかがわかりにくいと思います。そこで、今回の記事では`Azure App Service`と`Azure Static Web Apps`の比較や、それぞれのユースケースにも着目しながら、`Laravel`を使った簡単なWebアプリを公開します。

# Azure App Serviceとは
`Azure App Service`は、さまざまな言語とフレームワークに対応しており、REST APIやモバイルバックエンドもホストできます。
> Azure App Service は、Web アプリケーション、REST API、およびモバイル バックエンドをホストするための HTTP ベースのサービスです。

https://learn.microsoft.com/ja-jp/azure/app-service/overview

:::note info
参考：`Azure Static Web Apps`は、静的なHTML、CSS、JavaScriptのみをホストできます。つまり、静的なWebアプリであれば`Azure Static Web Apps`を選択し、動的なWebアプリであれば`Azure App Service`を選択するとよいでしょう。
:::

:::note info
参考：`Azure Static Web Apps`は静的なWebアプリを作成しますが、`Azure Functions`を利用してサーバーレスAPIを追加することで、動的なWebアプリにすることもできます。
:::


# Laravelアプリまでの流れ
以下の手順でLaravelアプリを公開します。
1. [Webアプリのソースコードを準備](#1-webアプリのソースコードを準備)
1. [Azureサービスのプロビジョニング](#2-azureサービスのプロビジョニング)
1. [AzureにWebアプリのデプロイ](#3-azureにwebアプリのデプロイ)
1. [Laravelのインストール](#4-laravelのインストール)
1. [データベースの設定](#5-データベースの設定)
1. [デプロイ済みアプリの確認](#6-デプロイ済みアプリの確認)

:::note warn
今回の記事では、[laravel-tasks](https://github.com/Azure-Samples/laravel-tasks)というサンプルWebアプリを使用するため、ローカル開発環境の構築やローカルでの開発過程は省略させていただいています。
:::

# 1. Webアプリのソースコードを準備
ローカルに[laravel-tasks](https://github.com/Azure-Samples/laravel-tasks)をクローンします。
```terminal
git clone https://github.com/Azure-Samples/laravel-tasks.git
```
これで必要なソースコードは準備できました。
# 2. Azureサービスのプロビジョニング
次に、使用するAzureサービスの準備を行います。
## 2.1. VSCodeの拡張機能のインストール
VSCodeの拡張機能で、`Azure App Service`をインストールします。
![スクリーンショット 2023-01-01 155408.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/a2c43e7c-ba8c-856f-c1dd-dbd9119b3d26.png)
`Azure Databases`も先にインストールしておきます。
![スクリーンショット 2023-01-01 180022.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/91802b28-0609-9cc8-42b6-d97c05159c15.png)

## 2.2. Azure App Serviceでアプリの構築
VSCodeのコマンドパレットより、「Azure App Service: Create New Web App」を実行します。
![スクリーンショット 2023-01-01 161142.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/d0bdffaa-904c-de16-3b29-dbac7ce5575a.png)
任意の作成済みサブスクリプションを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/3e0298da-0022-4a34-c73f-11a98dcfc0dc.png)
新しいWebアプリの名前を入力します。ここでは、「SampleAzureAppService」としました。
![スクリーンショット 2023-01-01 161317.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/42418d8f-2640-3ca2-1fda-0664b95ae534.png)
次に、ランタイムを選択します。ここでは、「PHP 8.1」を選択しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/1f69df27-e6d9-406a-6af1-dd88416a654d.png)
最後に、アプリ価格のTierを選択します。本記事では公開することだけが目的なので、ここでは「Free(F1)」を選びました。
![スクリーンショット 2023-01-01 161500.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/37e6f0e6-7f52-70c7-2f4f-3de6ca7353a4.png)
すると、Azureのアクティビティログから、アプリが作成されていることがわかります。チェックマーク(✅)がつくと無事にアプリの作成が終わったことがわかります。
![スクリーンショット 2023-01-01 162112.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/8b6d5289-b828-6226-f8d6-8e1696d79b0f.png)

:::note info
VSCodeのコマンドパレットは「Ctrl+Shift+P」で開くことができます。
:::
# 3. AzureにWebアプリのデプロイ
`Azure App Service`のセットアップが完了したので、Laravelアプリのデプロイを行います。

## 3.1. 公開されたWebアプリの確認
ここまでのところで、`Azure App Service`のアプリを作ることができました。この段階で既に`Azure App Service`のデフォルトアプリが公開されているので、確認してみましょう。アクティビティバーからAzureリソースを選択して、`App Services`フォルダの以下に含まれるアプリ(スクリーンショットでは`SampleAzureAppService`)のところで右クリックし、`Browse Website`を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/2995da42-0045-3ed3-f162-8611e4754ed2.png)
すると、ブラウザが起動して以下のような画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/ed1e363a-915c-11e8-1d04-1bb482689347.png)
これは、`Files`以下にある`hostingstart.html`が表示されたものです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/109c3d27-3ae2-15ee-7c03-beeeb7549686.png)
ですから、この`html`ファイルを変更してアップロードすることで、ブラウザでの表示を変更することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/edbc4b64-6290-d60e-8957-5d445d5b9264.png)

## 3.2. サンプルWebアプリのデプロイ
では次に、サンプルWebアプリのデプロイを行いましょう。作成したアプリを右クリックして表示されたメニューから`Deploy to Web App`を選択します。
![スクリーンショット 2023-01-01 162445.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/180a535b-2b96-6bcb-8c6f-a8d0f56b6c36.png)
すると、デプロイするWebアプリのフォルダを聞かれるので、`laravel-tasks`を選択します。
![スクリーンショット 2023-01-01 163304.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/49640600-094a-7690-1264-9b1c3754ad83.png)
デプロイすると、以前のデプロイが上書きされて取り消しできないけど大丈夫ですか？と確認のアラートモーダルが表示されますが、`Deploy`を押します。
![スクリーンショット 2023-01-01 163400.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/4d3a85eb-a84d-c733-7336-752e76b5f265.png)
以下のスクリーンショットのように、Outputパネルでデプロイが完了しましたと表示されたら、無事にサンプルWebアプリのデプロイは完了です。
![スクリーンショット 2023-01-01 163615.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/4a5ed326-6ef1-c703-1e47-72002c8cd898.png)
以下のスクリーンショットのように、`Files`以下が更新されていることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/88c23e5e-dd86-a448-0a99-65d2f95281c4.png)
しかし、このままではアプリを動かすことができません。試しに`Browse Website`を実行すると、以下のスクリーンショットのように403 Forbiddenが表示されます。この問題は`Laravel`をインストールし、`public/index.php`のシンボリックリンクを`wwwroot`以下に作成することで解決できます。
![スクリーンショット 2023-01-01 164158.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/e8bb1e02-ceea-58da-3af6-0e4c35159d3b.png)

# 4. Laravelのインストール
Webフレームワークの`Laravel`を`Composer`を使ってインストールします。

## 4.1. AzureのLinuxマシンへの接続
作成したアプリを右クリックし、`SSH into Web App`を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/ba5f289a-b561-0d8f-a792-1a70c443fbbf.png)
すると、ターミナルでWebアプリにSSHするためのコマンドを実行してくれます。10秒ほど待つと、以下のスクリーンショットのようにAzureのLinuxマシンへの接続に成功します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/8257cd10-43de-f53c-2650-3aa3ffa55fd5.png)

## 4.2. Composerのインストール
`Composer`はPHPの依存関係管理ツールです。まず、`/home/site/wwwroot`に移動します。
```terminal
root@05aaed07fc31:/home# cd /home/site/wwwroot
```
`/home/site/wwwroot`以下に移動したら、以下のそれぞれのコマンドを実行して`Composer`をインストールします。
```terminal
root@05aaed07fc31:/home/site/wwwroot# php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
```
```terminal
root@05aaed07fc31:/home/site/wwwroot# php -r "if (hash_file('sha384', 'composer-setup.php') === '55ce33d7678c5a611085589f1f3ddf8b3c52d662cd01d4ba75c0ee0459970c2200a51f492d557530c71c15d8dba01eae') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
Installer verified
```
```terminal 
root@05aaed07fc31:/home/site/wwwroot# php composer-setup.php
All settings correct for using Composer
Downloading...

Composer (version 2.5.1) successfully installed to: /home/site/wwwroot/composer.phar
Use it: php composer.phar
```
```terminal
root@05aaed07fc31:/home/site/wwwroot# php -r "unlink('composer-setup.php');"
```
以下のような表示がされれば、無事に`Composer`のインストールが終わりです。
```terminal 
root@05aaed07fc31:/home/site/wwwroot# php composer.phar
   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/
Composer version 2.5.1 2022-12-22 15:33:54
...(略)...
```

## 4.3. Laravelのインストール
`Composer`を使って、プロジェクトに必要なライブラリやパッケージをインストールします。Webフレームワークである`Laravel`も、このコマンドによって同時にインストールされます。
```terminal
root@05aaed07fc31:/home/site/wwwroot# php composer.phar install
Installing dependencies from lock file (including require-dev)
Verifying lock file contents can be installed on current platform.
Package operations: 110 installs, 0 updates, 0 removals

  - Downloading doctrine/inflector (2.0.4)
  - Downloading doctrine/lexer (1.2.3)
...(略)...
```
次に、プロジェクトにインストールされているライブラリやパッケージのバージョンを最新に更新するために、次のコマンドを実行します。
```terminal
root@05aaed07fc31:/home/site/wwwroot# php composer.phar update
```
最後に、`Laravel`がちゃんとインストールできているかを確認します。
```terminal
root@05aaed07fc31:/home/site/wwwroot# php artisan --version
Laravel Framework 8.83.27
```
上のように`Laravel`のバージョンが表示されれば、無事にインストールが完了していることが確認できます。

# 5. データベースの設定
laravel-tasksはデータベースを使用するWebアプリであるため、最後にデータベースの設定を行います。
## 5.1. Azure Database for MySQLの作成
`Azure Database for MySQL`のリソース作成をVSCode上で行うことができなかったため、ここではAzureポータルから作成することにします。まず、Azureポータルの検索窓から`mysql`と入力するとサービスで`Azure Database for MySQL`が表示されるので、選択します。
![スクリーンショット 2023-01-02 235557.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/515e912e-838e-33dc-c74d-14aa6e608c6f.png)
`Azure Database for MySQL`の作成ボタンを押下します。
![スクリーンショット 2023-01-02 235904.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/3b8ab832-8d8e-1098-47ca-c3f9c21707e0.png)
リソースの種類は推奨されているフレキシブルサーバーを選択します。
![スクリーンショット 2023-01-02 235941.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/6f9a6e70-0783-646e-14f0-cae852b6f596.png)
作成するデータベースの基本情報を入力します。
![スクリーンショット 2023-01-03 000655.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/94432c86-c6f7-4341-a228-9b89020e5ca7.png)
入力した情報に間違いがなければ、作成ボタンを押下します。
![スクリーンショット 2023-01-03 000724.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/df970db4-444d-bafe-612c-4f3b76a032fc.png)
すると、ファイアウォール規則の追加をするかどうかのモーダルが表示されます。本来であればファイアウォールの追加はするべきですが、今回のWebアプリでの運用は考慮していないため、規則の追加は行わないことにします。
![スクリーンショット 2023-01-03 000818.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/270d1db7-cb7b-ce6f-9c78-039c42a9a82d.png)
このように、デプロイが完了しましたと表示されれば、無事にデータベースの作成が成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/0c1939e1-ebc5-e6e9-0783-30a73a26567e.png)

Azureポータルのネットワークから「Azure 内の任意の Azure サービスにこのサーバーへのパブリック アクセスを許可する」をチェックして変更を保存します。
![スクリーンショット 2023-01-03 003540.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/82e6d230-7f6a-f739-98da-eb33b7b234c6.png)
サーバーパラメーターの変更をします。この変更はデータベースのマイグレーションを行うために必要な変更になります。検索窓に「require」と入力すると`require_secure_transport`パラメーターが表示されるため、値を`OFF`に変更して保存します。
![スクリーンショット 2023-01-03 003749.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/a7bf0db1-965c-0cba-57f2-6b13f56c6e6e.png)
最後に、データベースの作成を行います。左のメニューバーより「データベース」を選択し、「＋追加」ボタンを押下します。名前は`sample-mysql`と入力し、文字セットと照合順序はデフォルトのままにしておいて「保存」を押します。
![スクリーンショット 2023-01-03 004309.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/49942705-e1a6-cfaa-b8af-37bd25c754da.png)


## 5.2. 環境変数ファイルの編集
データベースの作成ができたため、接続するために以下の設定を`.env`ファイルに記述します。
```.env
APP_ENV=production
APP_KEY=
APP_DEBUG=false

DB_CONNECTION=mysql
DB_HOST=sample-mysql-server.mysql.database.azure.com
DB_PORT=3306
DB_DATABASE=sample-mysql
DB_USERNAME=ysaito
DB_PASSWORD=<自身で設定したパスワード>
```
ここで、`APP_KEY`の値は空になっていますが、`php artisan key:generate`で自動生成されます。
```terminal
root@05aaed07fc31:/home/site/wwwroot# php artisan key:generate
```

```terminal
root@05aaed07fc31:/home/site/wwwroot# chmod -R 777 storage
```

```terminal
root@05aaed07fc31:/home/site/wwwroot# php artisan migrate
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (1,212.46ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (1,123.16ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (1,120.43ms)
Migrating: 2019_12_14_000001_create_personal_access_tokens_table
Migrated:  2019_12_14_000001_create_personal_access_tokens_table (1,714.37ms)
Migrating: 2022_06_17_104844_create_tasks_table
Migrated:  2022_06_17_104844_create_tasks_table (545.73ms)
```
# 6. デプロイ済みアプリの確認
今の状態で、`<appname>.azurewebsites.net/public/`にアクセスすると`laravel-task`のWebアプリを閲覧することができます。
![スクリーンショット 2023-01-03 011816.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/04e80938-fa43-ab13-6f01-44ee6571d5f7.png)
URLの`/public`をなくすために、`/home/site/wwwroot`以下で`public/index.php`のシンボリックリンクを貼ります。
```terminal
root@05aaed07fc31:/home/site/wwwroot# ln -s public/index.php index.php
```
シンボリックリンクを貼ると、`<appname>.azurewebsites.net`でアクセスできるようになります。
![スクリーンショット 2023-01-03 020306.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/c2a3502f-863c-e02f-fe23-94410686c338.png)
「＋Add Task」でタスクを追加すると、以下のスクリーンショットの通りにタスク一覧が表示されることが確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/0db07178-e5e9-b121-96af-c520ba33f810.png)

# おわりに
本記事では、`Azure App Service`を使って`Laravel`アプリを公開しました。必要なリソースを必要な時に使えることや、デプロイが簡単にできることが大きなメリットであると感じました。また、本記事では活きてきませんでしたが、高可用性、DevOpsとの統合、セキリュティの確保というメリットもあるため、本番向けの運用の場合では更なる`Azure App Service`の強みが現れると思いました。