どうやら App Service on Linuxで PHP8 / Laravel8 のアプリを動かす時に、いろいろ気を付けることがあるようなので、回避策含め備忘録としてまとめておく。
主な注意点
大きく分けて二つ。
- PHPを動かす Web サーバーの設定
- ビルド方法
1. Web サーバー設定
App Service on Linuxの PHPのコンテナー イメージは、PHP7 までは apacheだったのが nginx に変更になった。
それに伴って、PHPを動かす設定も変えないといけないらしい。
# ちなみに、OS は Debian 10 (buster
)
具体的には、Startup Command
として、nginx へのリクエストを PHPアプリへルーティングする?ための設定を変更する処理を指定する。
まずは nginx の設定変更。
App Service on Linux内の nginx は /etc/nginx/sites-available/default
を見ているので、これをコピーして PHP8/Laravel8 の構成に合わせて変更する。
これをアプリケーション プロジェクトの scripts/default
として保存しておく。
scripts/default
server { #proxy_cache cache; #proxy_cache_valid 200 1s; listen 8080; listen [::]:8080; # 変更 1) index.php があるディレクトリを指定。これは Laravel8 の場合。 root /home/site/wwwroot/public; index index.php index.html index.htm; server_name example.com www.example.com; location / { index index.php index.html index.htm hostingstart.html; # 変更 2) 詳細は https://docs.microsoft.com/en-us/answers/questions/542749/deploying-an-app-service-with-laravel-8-and-php-8.html try_files $uri $uri/ /index.php?$args; } # 以下デフォルトのまま }
次に scripts/default
を /etc/nginx/sites-available/default
に戻して、nginx を再起動し、変更した設定を反映するスクリプトを書く。
同じく scripts/startup.sh
としておく。
scripts/startup.sh
#!/bin/bash cp /home/site/wwwroot/scripts/default /etc/nginx/sites-available/default service nginx reload
最後に App Service 側の Startup Command
を使って、起動時に scripts/starup.sh
を実行するよう設定する。
これで nginx と PHPとの間の設定は解決。
2. ビルド設定
2022 年 4 月現在、PHP8 のアプリは既定の設定のままだと App Service のビルド エンジンである Oryx でのビルド (compser install
コマンドの実行) ができない。
下記 Oryx の GitHubリポジトリの issue にある通り、Kudu コンテナー*1上でのビルド時に必要なファイル libonig.so.4
が見つからずエラーになってしまう。
追えるとこまで頑張ってみた感じ、これは、
- Kudu コンテナー上での
composer install
実行に使用される PHPバイナリーがlibong.so.4
とリンクしている - リンクされている
libonig.so.4
は、Debian 9 (コードネームstretch
) 向けのライブラリーである
https://packages.debian.org/search?keywords=libonig - でも Kudu コンテナーは Debian 10 (コードネーム
buster
) ベースのコンテナーである
だからlibonig.so.4
は入っていないし入れられない。
なので、この PHPバイナリーは今の Kudu コンテナーでは実行できない、という話。
たぶん PHPバイナリーをビルドしている環境が stretch
だったのではないか、という疑惑。
一応、修正済みの Oryx が GitHub上にはリリースされているので、Azure 上への次のリリース*2を待てばビルドできるようになるはず。
(以下 4/30 追記)
上記修正が適用されているかどうかは、Kudu コンソール上で oryx --version
を実行してみて、ReleaseTagName
が 20220427.1
かそれ以降になっているかを見たらいいっぽい。
(追記ここまで)
それが待てない人は以下の回避策をお試しあれ。
回避策 1. Oryx でビルドしない
最初はシンプルな策、Oryx でのビルドをやめる。
Oryx でビルドできないんだから、ローカルや CI 環境でビルドして、ビルド済みのものを App Service にデプロイしてしまえばいい。
App Service のアプリケーション設定で SCM_DO_BUILD_DURING_DEPLOYMENT
に false
を指定すると、デプロイ時のビルドは無効になる。
回避策 2. Kudu を stretch
ベースにする
issue で Corp. のエンジニアから出ている方法で、アプリケーション設定で SCM_DISABLE_BUSTER_KUDU
で true
を指定する。
すると、Kudu のコンテナーが stretch
ベースのものになるらしい。
試してみる。
既定の状態は buster
なのは上のスクショの通り。
次に SCM_DISABLE_BUSTER_KUDU
に true
を指定した状態。
おー確かに stretch
になった。マジかよ知らなかった*3。
これで libonig.so.4
が使えるので、composer install
はできるはず。
ただし、ビルドは stretch
ベースのコンテナー上で行われる一方で、実際のアプリケーションは buster
ベースのランタイム コンテナー上で動くことになるので、ライブラリーによってはこの違いで動かなくなる(かもしれない)。
回避策 3. PHPバイナリー自体を置き換える
Kudu コンテナー内での composer install
に使われている PHPバイナリーは、上記の通り stretch
上でビルドされたものと推察されるが、これは Oryx を起動した時にここからダウンロードして Kudu コンテナー内に展開したもの。
これを buster
上でビルドされた PHPバイナリーとに置き換えてしまえばいい。
そうすると
buster
ベースの KutuLite コンテナーbuster
向けの PHPバイナリーを使ってcomposer install
を実行してビルド- ランタイムも
buster
という感じで全て buster
で統一できてハッピー。
buster
向け PHPバイナリーは自前でビルドしてデプロイ パッケージに入れることもできるし、実は stretch
向けの PHPバイナリーと同じところにあるのでそっちも使える。
「置き換え」処理そのものは、Oryx が持っている「ビルド前後に任意のスクリプトを実行する」仕組みを使う。
PHPバイナリーの置き換えはビルドの前にやらないといけないので、 PRE_BUILD_SCRIPT_PATH
か PRE_BUILD_COMMAND
を使う。
単発コマンドでいい場合、またはワンライナーで書ける場合は PRE_BUILD_COMMAND
がいいが、スクリプトファイルを書く場合は PRE_BUILD_SCRIPT_PATH
でファイルを指定する。
例えば、下記のようなスクリプトを scripts/prebuild.sh
として配置するなら、PRE_BUILD_SCRIPT_PATH
に scripts/prebuild.sh
と指定する。
scripts/prebuild.sh
#!/bin/bashPHP_VERSION=8.0.17cd /tmp mkdir-p /tmp/oryx/platforms/php/${PHP_VERSION} curl -O https://oryx-cdn.microsoft.io/php/php-buster-${PHP_VERSION}.tar.gz tar -xzf /tmp/php-buster-${PHP_VERSION}.tar.gz -C /tmp/oryx/platforms/php/${PHP_VERSION}
これで、composer install
の直前に buster
向けの PHPバイナリーに差し替えができる。
懸念点は Corp. のエンジニアから「そっちのバイナリーは、依存モジュールが変わっているから、何が起こるか。。。」(超意訳)と言われたこと*4だけど、試した限り composer install
くらいなら動く。
もちろん自前でビルドして持ち込む場合は自己責任で。
startup.sh
など scripts
配下もまとめて GitHubに公開してみた。
一応、修正リリースと同じアプローチのはず。
ビルド エラー回避策のまとめ
ここまで書いたビルド設定に関する 4 種類の回避策のまとめ。
# | 回避策 | 設定方法 | メリット | デメリット |
---|---|---|---|---|
1 | Oryx でのビルドをやめる | SCM_DO_BUILD_DURING_DEPLOYMENT = false | ビルド環境の自由度が高い | CI 等のビルド環境が別途必要 |
2 | stretch ベースの Kudu コンテナー | SCM_DISABLE_BUSTER_KUDU = true | 設定簡単 | ビルド/ランタイム環境でベース OS が異なり、アプリ実行時に不整合が起こるかも。 |
3 | ビルド用 PHPバイナリーの変更 | PRE_BUILD_SCRIPT_PATH = <script_path> | ビルド/ランタイム環境の統一感 | 動くことは動くがエンジニアが前向きじゃない。自己責任。 |
4 | 次リリースを待つ | - | 公式方法。 | 「いつから使える」ってはっきりしたことは言えない |
あなたはどれを選びます?