Laravel Octaneとは?導入手順とFrankenPHP・Swoole比較を徹底解説

運用・保守・セキュリティ

「Laravel Octane」は、PHPアプリケーションを高速化するための公式パッケージです。通常のPHP-FPM環境では、リクエストのたびにフレームワーク全体を読み込み直しますが、OctaneはFrankenPHP・Swoole・RoadRunnerといった高性能アプリケーションサーバーを使ってアプリケーションをメモリ上に常駐させ、この読み込みコストをなくすことでレスポンス速度を大幅に改善します。この記事では、実際にLaravel 13環境へOctaneをインストールして動作確認した結果をもとに、導入手順・対応サーバーの選び方・本番運用時の注意点までを解説します。

Laravel Octaneとは?

Laravel Octaneは、Laravelアプリケーションを高性能なアプリケーションサーバー上で動かすための公式パッケージです。通常のPHP実行モデルでは、1リクエストごとにPHPプロセスがLaravelのコンテナやサービスプロバイダをゼロから初期化しますが、Octaneはアプリケーションを一度だけブートしてメモリに保持し、以降のリクエストは常駐したアプリケーションインスタンスで処理します。これにより、フレームワークの初期化コストがなくなり、スループットの向上とレイテンシーの低減を同時に実現できます。

Octaneが対応するアプリケーションサーバーは次の3種類です。

  • FrankenPHP:Go言語で書かれたモダンなPHPアプリケーションサーバー。Early Hints、Brotli/Zstandard圧縮などに対応し、現在octane:install実行時に推奨される標準の選択肢です。
  • Swoole(Open Swoole含む):PECL拡張として提供される高性能サーバー。並行タスク処理(Concurrent Tasks)やOctane専用キャッシュドライバなど、Octane独自の追加機能はSwooleでのみ利用できます。
  • RoadRunner:Go製のアプリケーションサーバー。PHP拡張のインストールが不要で、バイナリを配置するだけで動かせます。

インストール手順(実機検証済み)

実際にLaravel 13 + PHP 8.3の環境でOctaneをインストールし、動作を確認しました。まずComposerでパッケージを追加します。

composer require laravel/octane

次に、octane:installコマンドで設定ファイルと対応サーバーをインストールします。サーバーを明示的に指定しない場合は対話形式で選択できますが、--serverオプションで直接指定することも可能です。

php artisan octane:install --server=frankenphp

実行すると、FrankenPHPのバイナリ(検証時点で約160MB)が自動ダウンロードされ、プロジェクト直下に配置されます。

100% [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 167280264/167280264 bytes
 INFO  Octane installed successfully.

このコマンドを実行すると、config/octane.phpが生成されるとともに、.envOCTANE_SERVER=frankenphpが追記されます。ここで注意したいのが、config/octane.php内の既定値です。

'server' => env('OCTANE_SERVER', 'roadrunner'),

--server=frankenphpを指定してインストールしても、設定ファイル自体のフォールバック値はroadrunnerのままで、実際に使うサーバーは.envOCTANE_SERVERで決まります。デプロイ先の.envにこの値が入っているかは必ず確認してください。

Octaneサーバーの起動と動作確認

octane:startコマンドでサーバーを起動します。デフォルトではポート8000で待ち受けます。

php artisan octane:start --server=frankenphp --workers=4

実際に起動してcurlでリクエストを送ると、レスポンスヘッダーにServer: FrankenPHP Caddyが付与され、200 OKが返ることを確認できました。

$ curl -sI http://127.0.0.1:8000/
HTTP/1.1 200 OK
Server: FrankenPHP Caddy
X-Powered-By: PHP/8.5.8

サーバーの状態確認・再起動・停止は次のコマンドで行います。いずれも実際に実行し、応答メッセージを確認済みです。

# 稼働状況を確認
php artisan octane:status
# INFO  Octane server is running.

# デプロイ後にコードをメモリへ再読込(プロセスは止めない)
php artisan octane:reload

# サーバーを停止
php artisan octane:stop
# INFO  Stopping server..

開発中にコードの変更を即座に反映したい場合は--watchオプションを使います。事前にNode.jsとChokidarのインストールが必要です。

npm install --save-dev chokidar
php artisan octane:start --watch

ワーカー数とリクエスト上限の調整

Octaneは既定でCPUコア数分のワーカーを起動し、各ワーカーがリクエストを並行して処理します。ワーカー数は--workersで明示的に指定できます。

php artisan octane:start --workers=4

また、メモリリークの影響を抑えるため、Octaneは各ワーカーが500リクエストを処理するごとに自動的にワーカーを再起動します。この上限は--max-requestsで変更できます。

php artisan octane:start --max-requests=250

リクエストの最大実行時間はconfig/octane.phpmax_execution_time(既定30秒)で制御します。ファイルアップロードや外部APIとの通信など長時間かかる処理がある場合は、この値の見直しが必要です。

'max_execution_time' => 30,

本番環境での運用

本番環境では、OctaneのプロセスをSupervisorなどのプロセス監視ツールで常駐させます。公式ドキュメントで示されているSupervisor設定例は次の通りです。

[program:octane]
process_name=%(program_name)s_%(process_num)02d
command=php /home/forge/example.com/artisan octane:start --server=frankenphp --host=127.0.0.1 --port=8000
autostart=true
autorestart=true
user=forge
redirect_stderr=true
stdout_logfile=/home/forge/example.com/storage/logs/octane.log
stopwaitsecs=3600

Octaneサーバーの前段にはNginxなどのWebサーバーを配置し、静的アセットの配信とSSL終端を任せ、動的リクエストのみOctaneへプロキシするのが一般的な構成です。デプロイ後はoctane:reloadで新しいコードをワーカーへ反映させます。本番環境の構築手順とベストプラクティスもあわせて確認してください。

導入前に知っておきたい注意点

Octaneはアプリケーションをメモリに保持し続けるため、通常のPHP-FPM環境とは異なるクセがあります。これを知らずに導入すると、意図しない不具合を引き起こします。

グローバルな状態はリークする

staticなプロパティに値を追記し続けるコードは、リクエストをまたいでデータが蓄積し続けるメモリリークになります。

// メモリリークになる例
class Service
{
    public static array $data = [];
}

public function index(Request $request): array
{
    Service::$data[] = Str::random(10);

    return [];
}

この$dataはワーカーが再起動されるまでリクエストのたびに肥大化し続けます。ローカル開発中からメモリ使用量を監視し、こうした実装を作り込まないよう注意してください。

サービスコンテナ・Requestをコンストラクタに注入しない

シングルトンとして登録したクラスのコンストラクタでサービスコンテナやRequestインスタンスを直接受け取ると、最初のリクエストで解決されたインスタンスが以降のリクエストでも使い回されてしまいます。app()request()ヘルパー、あるいは解決用のクロージャを注入する形にすることで、常に最新のインスタンスを参照できます。

$this->app->singleton(Service::class, function () {
    return new Service(fn () => Container::getInstance());
});

Octane独自の高度な機能(Swoole限定)

Swooleを使う場合のみ、FrankenPHPやRoadRunnerにはないOctane独自の機能を利用できます。

並行タスク処理(Concurrent Tasks)

複数の処理をタスクワーカーで同時に実行し、配列の分割代入で結果を受け取れます。

use Laravel\Octane\Facades\Octane;

[$users, $servers] = Octane::concurrently([
    fn () => User::all(),
    fn () => Server::all(),
]);

ジョブキューによる非同期処理との使い分けが必要になるため、Laravel Queue Workerの基本と実践Laravelで実現する並列処理も参考に、レスポンス内で完結させたい処理はConcurrent Tasks、完了を待たずレスポンスを返したい処理はキューという形で使い分けると整理しやすくなります。

Octaneキャッシュドライバ

Swoole Tableを利用した専用キャッシュドライバで、1秒間に最大200万回という高速な読み書きが可能です。ただしサーバー再起動でデータは消えるため、永続化が必要なキャッシュには向きません。

Cache::store('octane')->put('framework', 'Laravel', 30);

通常のキャッシュ運用はcache — キャッシュの取得/保存を1行でLaravel キャッシュクリア完全ガイドを参照してください。

Laravel Octaneを導入すべきか

OctaneはAPIサーバーや高トラフィックなアプリケーションで特に効果を発揮します。一方で、次のようなケースでは無理に導入する必要はありません。

  • アクセス数が少なく、PHP-FPMのボトルネックが顕在化していないアプリケーション
  • グローバル状態のリークやメンテナンスコストを許容できないチーム体制
  • Swoole拡張のインストールなど、インフラ側の制約でPECL拡張を追加できない環境(この場合はバイナリ配置のみで動くFrankenPHPかRoadRunnerを選ぶ)

導入する場合も、まずはステージング環境でリクエストを継続的に流し、メモリ使用量が増加し続けないかを確認してから本番投入することをおすすめします。

よくある質問

Q. OctaneはSwoole・RoadRunner・FrankenPHPのどれを選べばいいですか?

A. 追加のPECL拡張を入れずに導入したい場合はFrankenPHPかRoadRunnerが手軽です。Concurrent TasksやOctane専用キャッシュドライバなどOctane独自の機能を使いたい場合はSwooleを選択してください。迷う場合は、現在octane:installで優先的に案内されるFrankenPHPから試すのがおすすめです。

Q. コード変更のたびにサーバーを再起動する必要がありますか?

A. はい。Octaneはアプリケーションをメモリに保持するため、ファイルを変更しただけでは反映されません。開発中は--watchオプション、デプロイ後はoctane:reloadコマンドで反映させます。

Q. 既存のLaravelアプリにそのままOctaneを導入できますか?

A. 多くの場合は導入可能ですが、グローバルな状態やコンストラクタでのコンテナ・Request注入がないか事前にコードを見直す必要があります。導入後はステージング環境でメモリ使用量が増加し続けないかを確認してください。

まとめ

Laravel Octaneは、FrankenPHP・Swoole・RoadRunnerといった高性能アプリケーションサーバーでアプリケーションを常駐させることで、PHPアプリケーションのパフォーマンスを大幅に向上させるパッケージです。導入自体はComposerとoctane:installコマンドだけで完了しますが、メモリに常駐する仕組みゆえのグローバル状態のリークや、コンストラクタでのコンテナ・Request注入といった落とし穴があります。本番投入前にステージング環境で十分に検証し、アプリケーションの特性に合ったアプリケーションサーバーを選択してください。Artisanコマンド全般はLaravelのArtisanコマンド徹底解説|最速チートシート&現場ノウハウでも一覧できます。

レン (Wren)

こんにちは。レンです。

Laravelのコードの森に住んでいる、小さな案内役です。
ルーティングの枝やクラスの影を歩きながら、コードの流れや仕組みを眺めています。

このサイトでは、Laravelの基本から実装のコツまで、開発で役立つポイントを静かに整理しています。
難しいことを増やすのではなく、コードの見通しが少し良くなるヒントを届けるのが役目です。

「この処理はどこに書くのがいいのか」
「Laravelではどう考えると整理できるのか」

そんな疑問に、小さなメモを残すような気持ちで記事を書いています。

コードを書いている途中で迷ったとき、
このサイトが少し立ち止まって整理できる場所になればうれしいです。

レン (Wren)をフォローする

コメント