移行

このガイドでは、既存の PHP アプリケーションを OxPHP に移行します。現在使っているもの(nginx + PHP-FPM、または FrankenPHP や RoadRunner)に対応するセクションから始め、移行を決める前に引き継がれないものを読んでください。

nginx + PHP-FPM からの移行

ほとんどのアプリケーションはコードを変更せずに移行できます。デフォルトのモードは各リクエストをクリーンな PHP の状態から実行します。これは PHP-FPM と同じライフサイクルなので、必要な作業は設定の変換です。デプロイ例には、Laravel、Symfony、WordPress、Drupal、Magento などの完全なレシピがあります。

1. try_files に合ったルーティングモードを選ぶ

nginx OxPHP
try_files $uri /index.php?$query_string(Laravel、Symfony、Yii) ENTRY_FILE=index.php(フレームワーク)
複数の PHP エントリーポイントを持つ try_files $uri $uri/ /index.php(WordPress、OpenCart) ENTRY_FILE 未設定(従来型)
シングルページアプリ向けの try_files $uri /index.html ENTRY_FILE=index.html(SPA)

2. イメージをビルドする

クイックスタートにある 2 行の Dockerfile から始めます。拡張機能はスレッドセーフな PHP 向けに、OxPHP イメージと同じ PHP マイナーバージョンの php:*-zts-alpine ステージでビルドする必要があります。本番環境での PHP 拡張機能のインストールを参照してください。

Warning

使用しているすべての PECL 拡張機能が ZTS に対応していることを確認してください。OxPHP はスレッドセーフな PHP でのみ動作するため、ZTS に対応していない拡張機能は読み込めません。

3. 設定を変換する

イメージは php.ini を読み込みません。PHP の設定(memory_limit、upload_max_filesize、OPcache、…)は、プロジェクト内の任意の場所に置いた独自のファイル(たとえば docker/php.ini)にまとめ、それをイメージの PHP 設定ディレクトリにコピーします。このディレクトリはプロジェクト内ではなく、コンテナ内のパスです。

Dockerfile
FROM ghcr.io/oxphp/oxphp:0.13.0 COPY docker/php.ini /usr/local/etc/php/conf.d/zz-app.ini COPY --chown=www-data:www-data . /var/www/html/public

PHP はこのディレクトリ内のすべての .ini ファイルをアルファベット順に読み込み、最後の値が優先されます。そのため zz- という接頭辞を付けると、イメージ自身のファイルの後に自分の設定が適用されます。ファイルをボリュームとしてマウントする方法も使えます。PHP の設定を参照してください。

それ以外の設定は環境変数に対応します。

nginx / PHP-FPM OxPHP
listen 443 ssl、ssl_certificate TLS_CERT、TLS_KEY、TLS_MIN_VERSION。TLS を参照
pm = static / pm = dynamic、pm.max_children PHP_WORKERS=N / PHP_WORKERS=MIN:MAX
php_admin_value[...]、php.ini 独自の .ini ファイルをイメージ内の /usr/local/etc/php/conf.d/ にコピー(上記参照)
gzip on、brotli on デフォルトで有効。COMPRESSION_ENCODINGS で設定。圧縮 を参照
静的ファイル向けの expires 30d STATIC_MAX_AGE(デフォルト 30d)
limit_req RATE_LIMIT、RATE_WINDOW_SECONDS(IP ごとの固定ウィンドウ)。レート制限 を参照
set_real_ip_from、real_ip_header TRUSTED_PROXIES。信頼済みプロキシ を参照
error_page 404 /404.html ERROR_PAGES_DIR({status}.html ファイルを配置)。エラーページ を参照
access_log ACCESS_LOG=all または error(JSON 行)。アクセスログ を参照
location ~ ^/uploads/.*\.php$ { deny all; } PHP_DENY_PATHS=/uploads/**。PHP 実行拒否リスト を参照
pm.status_path、ping.path INTERNAL_ADDR(/health と /metrics)。ヘルスチェック を参照
fastcgi_finish_request() oxphp_finish_request()。早期レスポンス を参照

4. 挙動の違いを確認する

  • max_execution_time はウォールクロック時間を計測します。PHP-FPM では、データベースや HTTP 呼び出しを待つ時間はカウントされませんが、スレッドセーフな PHP ではカウントされます。これまで上限に達したことのない遅いエンドポイントが、504 を返し始めることがあります。タイムアウトを参照してください。
  • php_sapi_name() は cli-server を返します。fpm-fcgi で分岐しているコードには、別のチェックが必要です。function_exists('oxphp_request_id') を使ってください。
  • $_SERVER のいくつかのキーが異なります。SERVER_ADDR、PATH_TRANSLATED、REDIRECT_STATUS は設定されず、PHP_AUTH_USER / PHP_AUTH_PW は抽出されません。代わりに HTTP_AUTHORIZATION を読んでください。PHP-FPM との違いを参照してください。
  • フレーミングはデフォルトで制限されています。レスポンスには X-Frame-Options: SAMEORIGIN と、それに対応する frame-ancestors ポリシーが付きます。フレーミングを別の場所で管理している場合や、アプリを別のオリジンに埋め込む場合は、FRAME_OPTIONS=off を設定してください。クリックジャッキング対策を参照してください。

5. 既存のスタックと並行してロールアウトする

OxPHP を nginx + PHP-FPM と並べて実行し、既存のロードバランサーを通じてトラフィックの一部を OxPHP に向けます。プローブには /health/readiness を使い、残りを移す前に /metrics でエラー率とレイテンシを比較してください。

6. ワーカーモードは最後に有効にする

まずデフォルトのモードで移行します。その後、WORKER_MODE_ENABLED=true を設定し、ENTRY_FILE にワーカースクリプトを指定します。静的プロパティに保持される状態や長寿命の接続がリクエスト間で維持されるようになるため、有効にする前にリセットされるものと維持されるものを読んでください。

FrankenPHP または RoadRunner からの移行

ワーカースクリプトの形はそのままです。一度ブートストラップしてから、リクエストを処理します。frankenphp_handle_request() のループを、1 回の oxphp_worker($handler) 呼び出しに置き換えてください。ループは OxPHP が実行し、リクエストごとにハンドラーを呼び出します。ハンドラー内では、スーパーグローバルまたは oxphp_http_request() からリクエストを読み取ります。RoadRunner の PSR-7 の waitRequest() / respond() ループに相当するものはありません。アプリケーションのハンドラーを同じコールバックに移してください。oxphp_worker() とワーカーモードを参照してください。

MAX_REQUESTS カウンターを削除する

相当する機能はありませんが、必要もありません。ワーカーは N リクエストごとに再起動する前提で作られてはおらず、そうしてもリークを隠すだけです。リークが疑われる場合は、再起動ではなく次の方法で追跡してください。

  • ワーカーごとに oxphp_worker_memory_bytes をグラフにし、一定の増加が続いていないかを監視します。
  • 安全策として WORKER_MAX_MEMORY_MIB を設定します。上限を超えたワーカーはコンテナのメモリが尽きる前に置き換えられ、そのようなリサイクルはそれぞれ oxphp_worker_recycles_by_reason_total{reason="max_memory"} でカウントされます。
  • この上限が計測するのは PHP 自身のヒープだけです。拡張機能を多用するスタックでは、Worker::current()->rss() を独自のしきい値と比較し、Worker::scheduleExit() を呼び出してください。

引き継がれないもの

  • OxPHP にはリバースプロキシやアップストリームの機能がありません。proxy_pass も WebSocket サーバーもありません。nginx がほかのサービスの前段も担っている場合は、それらのルート用に OxPHP の前にプロキシを残してください。
  • 1 つのインスタンスが扱うポートとプロトコルは 1 つです。プレーンな HTTP か HTTPS のどちらかを提供し、両方は提供しません。そのため、ポート 80 から HTTPS へのリダイレクトにはプロキシか 2 つ目のインスタンスが必要です。証明書は起動時に読み込まれるため、更新には再起動が必要です。TLS を参照してください。
  • HTTP/3 と 103 Early Hints はまだ利用できません。ロードマップを参照してください。
  • OxPHP は Linux 上でのみ動作し、Docker イメージとして配布されます。apt や brew のパッケージはありません。PHP 8.4 と 8.5 をサポートしています。

エージェント向けプロンプト

これらのプロンプトは、OxPHP ドキュメント MCP サーバー を接続したエージェントを前提としています — 必要なページはエージェントが自分で読み取ります。

prompt
このアプリケーションを nginx と PHP-FPM から OxPHP に移行してください。OxPHP ドキュメント MCP サーバー経由で `getting-started/migration` ページを読んでください。 このリポジトリにある nginx の server ブロック、PHP-FPM のプール設定、php.ini の上書きを OxPHP の Dockerfile と環境変数に変換し、`try_files` のルールからルーティングモードを選んだうえで、このコードに当てはまる挙動の違いとサポートされていない機能を、影響するファイルとともにすべて挙げてください。
prompt
このリポジトリにある FrankenPHP または RoadRunner のワーカーを OxPHP に移植してください。OxPHP ドキュメント MCP サーバー経由で `getting-started/migration` ページを読んでください。 ワーカースクリプトを 1 回の `oxphp_worker()` 呼び出しを中心に書き直し、N リクエストごとにワーカーを再起動するカウンターがあれば削除したうえで、その代わりに設定すべきメトリクスとメモリ上限を教えてください。

次のステップ

  • ルーティング — 従来型、フレームワーク、SPA、ワーカーの各ルーティングモードの詳細
  • Docker ガイド — 開発用および本番用の Dockerfile、Compose 設定、PHP ini のマウント
  • 設定 — 環境変数の完全なリファレンス
  • ワーカーモード — 一度ブートストラップして複数のリクエストを処理する永続的な PHP ワーカー
  • デプロイ例 — Laravel、Symfony、WordPress、Drupal、Magento などの完全なレシピ