Check! Azure Web Apps に既存の Linux + PHP (CakePHP 2.x) 環境を移植する

こんにちは、 @dz_ こと大平かづみです。

Prologue - はじめに
====
[Azure Web Apps](https://azure.microsoft.com/ja-jp/services/app-service/web/ "Web App Service | Microsoft Azure") を含め、 PaaS はインフラ周りのメンテナンス負荷が削減できるので、慣れておくと選択肢が広がります。

そこで今回は、**既存の Linux x PHP 環境** を Azure Web Apps に移行することを想定し、ポイントをピックアップしてみます。

サンプルとして、日本でよく使われてるフレームワーク CakePHP 2.x を利用します。

作業環境
====
## 想定する既存環境
- CakePHP 2.x のプロジェクト
    - Git 管理下
- Linux
    - Apache

## デプロイ先
- Microsoft Azure
    - Web Apps
        -  MySQL In App (Preview) も使ってみる

要点ピックアップ
====
PHP 自体は、ソースコードさえあれば普通に動く
---
Azure Web Apps は、 Windows x  IIS で構成されていますが、PHP のコードをデプロイしドキュメントルートさえ指定すれば、基本的に動作するようになっています。

本当にあっさり動きます(笑)

（※一部、細かな注意点はありますので、後述します。）

そして、コードをデプロイするには、継続的インテグレーションが便利です。GitHub や BitBucket, Local Git などもサポートされてますので、チェックしてみてください。

- [Azure App Service への継続的なデプロイ | Microsoft Azure](https://azure.microsoft.com/ja-jp/documentation/articles/app-service-continuous-deployment/ "Azure App Service への継続的なデプロイ | Microsoft Azure")
- [Azure WebAppsにGitLab連携でデプロイしてみよう | dotstudio](https://dotstud.io/blog/azure-webapps-gitlab-connect/ "Azure WebAppsにGitLab連携でデプロイしてみよう | dotstudio")
    - デフォルトではサポートされていない [GitLab](https://gitlab.com/ "GitLab") のリポジトリ連携について紹介されています。



### App Service on Linux (Preview) について
ちなみに、最近、 App Service on **Linux** がパブリックプレビューで公開されました。まだ米国リージョンのみですが、いつか日本リージョンで展開されることを楽しみにしています！

- [App Service on Linux | Microsoft Azure](https://azure.microsoft.com/ja-jp/documentation/articles/app-service-linux-readme/ "App Service on Linux | Microsoft Azure")



MySQL との相性
----
Linux x PHP で稼働しているサービスは、MySQL も使っていることが多いですね。Azure でも、以下のように MySQL を利用する方法が提供されています。（下記以外にもあります。）

| 選択肢 | 概要 |
|--------|-----|
| MySQL Database | [ClearDB](http://w2.cleardb.net/ "ClearDB – The Ultra Reliable, Geo Distributed Data Services Platform") により提供されるマネージドの MySQL サービス（無料プランあり） |
| MySQL In App (Preview) | Web App 内に MySQL がインストールされる |

これらは、新規作成時に「Web App + MySQL」を利用すると、Web App と MySQL を同時に作成することができます。

また、個別に作成することもできます。

- [ポータルから MySQL Database （ClearDB による提供）を作成する](https://azure.microsoft.com/ja-jp/documentation/articles/store-php-create-mysql-database/ "Azure で MySQL データベースを作成して接続する")
- Web App のメニューから MySQL In App の有効/無効を設定する

### 注意点

なお、MySQL In App については、 まだ **プレビュー** かつ、スケーリングは考慮されていないので検証までにとどめることをお勧めします。

> MySQL In App を使ったアプリは、運用環境での使用を意図したものではありません。また、単一のインスタンスの範囲を超えてスケールすることもありません。 

また、 Web App 内のストレージ領域を使うので、Free、Shared プランの場合はストレージのクオータ制限についてよくご確認の上、ご自身の判断でご利用くださいませ。

細かなチェックポイント
====

ドキュメントルートの設定
----

PHP や CakePHP に限った話ではないのですが、ドキュメントルートを明示的に設定することができます。

Web App のドキュメントルートは `site\wwwroot` で、継続的インテグレーションを設定するとソースコードはここに展開されます。

今回想定している既存のプロジェクトでは、必ずしもリポジトリのトップがドキュメントルートとは限りませんので、異なる場合は明示的に指定しましょう。

ポータルの、 Web App > 「アプリケーション設定」 > 「仮想アプリケーションとディレクトリ」で設定できます。

![20161029_azure-webapp_cakephp_001.png](https://qiita-image-store.s3.amazonaws.com/0/3812/80a016d4-d856-4fe5-046b-f1b8e5026764.png)

URLリライトは `web.config` を使う
----
CakePHP は、 `.htaccess` を使った URL リライトで動作しますが、IIS は `.htaccess` を読まないので、以下のようなエラーが発生します。

```
URL rewriting is not properly configured on your server.
	1) Help me configure it
	2) I don't / can't use URL rewriting
```

IIS で URL リライトをするには、 `web.config` に記述します。サンプルとして、デフォルトの `.htaccess` に対する `web.config` の例を記載します。

```apache:CakePHP2.xの.htaccess
<IfModule mod_rewrite.c>
	RewriteEngine on
	# Uncomment if you have a .well-known directory in the root folder, e.g. for the Let's Encrypt challenge
	# https://tools.ietf.org/html/rfc5785
	#RewriteRule ^(\.well-known/.*)$ $1 [L]
	RewriteRule ^$ app/webroot/ [L]
	RewriteRule (.*) app/webroot/$1 [L]
</IfModule>
```

```xml:web.config変換例
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>

        <rule name="Rule Root" stopProcessing="true">
          <match url="^(.*)$" ignoreCase="false"/>
          <conditions>
             <add input="{REQUEST_URI}" pattern="^$" />
          </conditions>
          <action type="Rewrite" url="app/webroot/" appendQueryString="true"/>
        </rule>

        <rule name="Rule basic" stopProcessing="true">
          <match url="^(.*)$" ignoreCase="false"/>
          <conditions>
             <add input="{REQUEST_URI}" pattern="(.*)" />
          </conditions>
          <action type="Rewrite" url="app/webroot/{R:1}" appendQueryString="true"/>
        </rule>

      </rules>
    </rewrite>
  </system.webServer>
</configuration>
```

![20161029_azure-webapp_cakephp_002.png](https://qiita-image-store.s3.amazonaws.com/0/3812/e08d1e8f-93ea-ace2-0055-a7b815b3c4b6.png)

パスには要注意
----
OS間の違いにより、ディレクトリの区切りが認識できないことがあります。

| OS | ディレクトリの区切り |
|----|--------------------|
| Linux | `/` |
| Windows | `\` |

私の場合は、環境ごとに切り替える処理を書く代わりに、 Web Apps の「アプリ設定」を利用して、環境変数を読むだけで済むようにしました。 `getenv()` で取得できるようになります。詳細はこちらをご参考ください。

- [Azure Web アプリの構成 - Azure への PHP Web アプリの作成、構成、デプロイ](https://azure.microsoft.com/ja-jp/documentation/articles/app-service-web-php-get-started/#azure-web "Azure Web アプリの構成 - Azure への PHP Web アプリの作成、構成、デプロイ")

PHPモジュールについて
----
Web App が持つPHPモジュールについては、 `phpinfo()` で確認できます。

なお、CakePHP でMySQLを使う際には `PDO` と `pdo_mysql` が必要ですが、Web App にはすでにインストールされています。

また、任意の PHP モジュールを追加したい場合はこちらをご参考ください。

- [Check! Azure Web Apps で PHP 拡張モジュールを利用する（複数可）](http://qiita.com/dz_/items/cca05e4b7caa8e105346 "Check! Azure Web Apps で PHP 拡張モジュールを利用する（複数可）")

Epilogue - おわりに
====
ここにあげたチェックポイントは、CakePHP に限らず、Linux x PHP で動いている環境を移植するときに参考になると思います。

余談
----
実は、Azure Web Apps には Marketplace があり、 PHP を使ったものも多数あります。

- [PHP - Microsoft Azure Marketplace](https://azure.microsoft.com/en-us/marketplace/?term=PHP "PHP - Microsoft Azure Marketplace")

この中に CakePHP もあるのですが、既存の環境を移植するには少し煩雑かと思い、あえて Marketplace を使わない方法をまとめようと思った次第です。


なにはともあれ、快適な環境で開発できますように！