FrankenPHP: モダンなPHPアプリサーバー
(frankenphp.dev)- PHPアプリを別途PHP-FPMなしで動かしたいデプロイフローにおいて、FrankenPHPはCaddyに公式PHPランタイムを組み込んだGoベースのアプリサーバーとして、PHP WebアプリとCLIスクリプトを1つのコマンドで実行できるようにする
- HTTP/1.1・HTTP/2・HTTP/3、自動HTTPS証明書、Brotli/Zstandard/Gzip圧縮、構造化ロギング、Prometheusメトリクスを標準機能としてまとめ、サーバー設定を簡素化する
- Worker modeはアプリを一度起動してメモリに保持し、API Platformアプリの独自ベンチマークではFPMより3.5倍高速な結果を示したと説明している
- PHP 8.2+、ほとんどのPHP拡張、Caddyモジュールと互換性があり、OPcache・XDebugのような人気拡張もネイティブ対応している
- Dockerイメージ、Kubernetes、クラウドプラットフォーム、スタンドアロンの静的バイナリ配布をサポートし、PHPアプリのデプロイ単位をシンプルにできる
実行方式と基本的な利用フロー
- FrankenPHPはGoで書かれたモダンなPHPアプリサーバーを志向しており、PHPアプリサーバーのインストールと実行を1コマンド中心で構成している
- インストール例はOSごとに分かれている
- Linux/macOS:
curl https://frankenphp.dev/install.sh | sh - Windows PowerShell:
irm https://frankenphp.dev/install.ps1 | iex
- Linux/macOS:
- ローカル実行ではWebサーバーとCLIの両方を扱える
frankenphp php-server -r public/:public/ディレクトリを配信frankenphp php-cli script.php: コマンドラインPHPスクリプトを実行
- Docker実行も同じイメージで処理する
dunglas/frankenphpイメージでpublic/ディレクトリを配信- 同じイメージで
php script.phpのようなCLIスクリプトも実行可能
- 設定はCaddyベースで、例では
localhostブロック内で圧縮を有効にし、php_serverで現在のディレクトリのPHPファイルと静的アセットを処理する
サーバー機能とPHP互換性
-
Webサーバー機能
- 公式PHPランタイムをCaddyに内蔵している
- HTTP/1.1、HTTP/2、HTTP/3をネイティブサポートする
- Let’s EncryptまたはZeroSSLによるHTTPS証明書の生成・更新・失効を自動化する
- Brotli、Zstandard、Gzip圧縮を標準サポートする
- 構造化ロギングとPrometheus対応を含む
-
PHP実行環境
- PHP 8.2+、ほとんどのPHP拡張、すべてのCaddyモジュールと互換性がある
- OPcacheとXDebugを含む人気のPHP拡張をネイティブサポートする
- PHP-FPMは不要で、Go Webサーバー向けに作られた独自SAPIを使用する
Worker modeと性能志向の機能
- Worker modeはアプリケーションを一度起動した後にメモリへ保持し、リクエストを数ミリ秒以内で処理できる準備状態にしておく
- Symfony、API Platform、Laravelでネイティブサポートされている
- PSR-7なしで既存のPHPスーパーグローバルを使用する
- アプリがWorker modeと互換でなくてもそのまま配信できる
- コード変更時にワーカーを自動再起動するwatcherを提供する
- API Platformアプリ基準の独自ベンチマークではFPMより3.5倍高速な性能を示したと紹介している
デプロイとパッケージング
- Dockerイメージでクラウドネイティブアプリをデプロイできる
- Kubernetesおよびモダンなクラウドプラットフォームと互換性がある
- PHP Webアプリケーションとコマンドラインツールをスタンドアロンの静的バイナリとしてパッケージできる
- 1つのサービスと1つのバイナリで動作し、外部サービスは不要だと説明している
追加のWebプラットフォーム機能
- 103 Early Hintsをサポートし、Cloudflareの記事を根拠にWebサイトの読み込み時間を**30%**改善できる機能として紹介している
- 組み込みのMercureハブを通じて、PHPアプリから接続されたブラウザへイベントを送信し、ブラウザがJavaScriptイベントとしてペイロードを即座に受け取れる
- Graceful reloadで無停止デプロイをサポートする
1件のコメント
Hacker News のコメント
ゾウのフランケンシュタインのキャラクターが奇妙で、不格好で、かわいい。デザイン、色、コピー、アニメーションもすっきりしている。しばらく PHP 開発から離れていた立場から見ると、価値提案がよく伝わり、小さく素早く始めるのに良さそうに見える
いまいちなソフトウェアやこじれた依存関係を隔離するために、コンテナを8個立ち上げたくはない。インストール可能なソフトウェアを出す代わりに、「自分のマシンでは動く」を包んで世の中に投げるようなやり方は好きではない。懐かしさで一度触ってみることはあるかもしれないが、こういうものをもう本番環境に入れたいかはよく分からない
昔の LAMP のようにやや複雑な Apache 設定が必要な方向よりも、言語はこういう方向に進むべき
これも試してみるつもりだが、nginx でも Apache でもボトルネックに遭遇したことはない。どちらも長くても数分で立ち上げられる
Apache + mod_php のように単一サービスとして実行され、PHP と他言語のマルチプロセッシング、静的ファイル、リバースプロキシを処理し、ファイルやソケット経由のランタイム方式で自身と PHP を一つの設定で扱える: https://unit.nginx.org/configuration/#php
実際の設定例は https://github.com/PrivateBin/docker-unit-alpine/blob/master... で、生成されるコンテナイメージもかなり小さくできる: https://hub.docker.com/r/privatebin/unit-alpine
Apache を再起動した以外に、特に何かした記憶はない
LoadModule proxy_fcgi_module "/usr/lib/apache2/modules/mod_proxy_fcgi.so"とSetHandler "proxy:fcgi://127.0.0.1:9000"程度だ。Apache を設定する方法と概念的に似た Nginx の例もあり、必要なパッケージのインストールまで含まれている: https://news.ycombinator.com/item?id=37443911似た結果を得られる事前ビルド済みのコンテナイメージもあるが、内部がどう動いているか見たいなら自分でやってみることもできる。昔の Java アプリケーションサーバーで Tomcat や GlassFish を手動設定していた頃よりは確実に簡単で、どんな環境でも単一の実行コマンドの方が良いのは確かだが、LAMP が他のスタックに比べてそこまで悪いわけではない
バイナリがあれば Electron アプリに同梱するのも簡単になる
php -S 0.0.0.0:8000 public/index.phpただしシングルスレッドで遅いので本番環境向きではない。FrankenPHP は有望に見えるが、コア/スレッド制限の問題[2]も本番では問題になりそうだ。それでも pure-todo[1] プロジェクトに一度適用して、同じ問題があるか見てみてもよさそう。デフォルトの Docker イメージはかなり良さそうだ
1: https://github.com/sandreas/pure-todo
2: https://github.com/dunglas/frankenphp/discussions/294
ページ上部の警告を参照: https://www.php.net/manual/en/features.commandline.webserver...
この文脈で比較対象にするのが公平なのかもよく分からない
PHP_CLI_SERVER_WORKERSを設定すれば、複数スレッドで実行できるユーザー数の少ない小規模サイトなら、他の「本番対応」環境に比べて何を取りこぼすのか知りたい
いくつかのコマンドだけで本番対応になり、FPM より3.5倍速いというが、自分の環境では FPM の性能の1% 程度で動作する。実行ファイルも試したが同じ問題で、hello world なら少なくとも 200K rps は期待していた
ほとんどのベンチマークでは、ワーカーモードを有効にした場合、FrankenPHP は通常 FPM よりはるかに高速で、およそ3倍程度です。それでもいくつか例外的なケースがあり、PHP のメンテナーたちと一緒に修正に取り組んでいます
Caddy 自体は PHP と併用しても非常に高い性能が出るので、かなり奇妙な状況です
現在は did not complete として最下部にあります
性能問題があります。それを除けば、本当に有望なプロジェクトです
ただし深く掘り下げたわけではなく、テストも一般的な設定ではなく Docker 内で行いました。WordPress もほぼデフォルト設定で、重いテーマのようなものがないため現実的な条件ではありませんでした。それでもテストをやり直して、もっと理解を深めたいです
ただし 103 Early Hints でアセットを事前読み込みし、ページロードの遅延を30%減らすことはできます。それでも FrankenPHP は WordPress で HTTP キャッシュを有効にしやすくし、デプロイも簡素化します。WordPress と FrankenPHP 専用のプロジェクトもあり、Souin Go ライブラリを使った WordPress 向けの組み込み HTTP キャッシュが含まれています: https://github.com/StephenMiracle/frankenwp
Apache のメモリを少し節約し、より多くの PHP リクエストを処理する余地を作れます
docker run -v $PWD:/app/public -p 443:443 \ dunglas/frankenphpアプリを配信する Docker コンテナを自分で作りたいなら、新しい Debian を必要なコンテナに変えるには、次のコマンドで十分そうです:
apt install -y apache2 libapache2-mod-phpと/etc/apache2/sites-enabled/000-default.confの設定友人たちと一緒に、複数の人気言語とフレームワークで、ゼロから動作中の Web アプリケーションに至るまでの過程を示すリポジトリをメンテナンスしています: https://github.com/no-gravity/web_app_from_scratch
xdebug を有効にするたびに、デバッグセッション後に Apache を再起動しなければなりません。昨日から apache2 を php-fpm として使うよう設定し始めましたが、少なくとも開発環境では、この FrankenPHP が自分たちに合うのか気になります。ただ、ドキュメントで php 拡張をインストールする方法を見つけられません
000-default.conf仮想ホストは 443 から 80 にリダイレクトするのでしょうか?FPM とそのシェアードナッシングアーキテクチャは、かつての PHP の成功の核心でしたが、同時に PHP の足かせでもあったと感じています