Laravel Octaneとは?導入手順とFrankenPHP・Swoole・RoadRunnerの選び方を徹底解説

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

「Laravel Octane」は、Laravelアプリケーションのスループットとレスポンス速度を極限まで引き上げるための公式パッケージです。従来のPHP-FPM環境ではリクエストごとにフレームワーク全体を初期化(ブート)していましたが、OctaneはFrankenPHP・Swoole・RoadRunnerといった高性能アプリケーションサーバー上でアプリケーションをメモリに常駐させ、初期化コストをゼロに抑えます。

この記事では、Laravel Octaneの仕組みから導入手順、3大対応サーバー(FrankenPHP・Swoole・RoadRunner)の徹底比較、本番環境でのSupervisor・Nginx設定、そして導入時に必ず押さえるべきメモリリーク・状態汚染(State Leaks)の対策まで、実機検証済みのコードとともに徹底解説します。

  1. Laravel Octaneとは?なぜ劇的に高速化するのか
    1. 従来のPHP-FPMとOctaneのライフサイクルの違い
  2. 3大アプリケーションサーバーの特徴と選び方(FrankenPHP / Swoole / RoadRunner)
    1. どれを選ぶべきか?選び方の基準
  3. Laravel Octaneのインストールと初期セットアップ
    1. 1. 前提条件の確認
    2. 2. Composerパッケージのインストール
    3. 3. octane:install コマンドの実行
    4. 4. 設定ファイルと環境変数の確認
  4. Octaneサーバーの起動と基本コマンド
    1. サーバーの起動(octane:start)
    2. 開発時のホットリロード(–watch)
    3. 稼働確認・コード再読み込み・停止
    4. ワーカー数と最大リクエスト数のチューニング
  5. Octaneの高度な機能と活用例
    1. 1. 並行タスク処理(Octane::concurrently)
    2. 2. インメモリキャッシュ(Swoole Table)
  6. 導入時の必須注意点と状態汚染・メモリリーク防止策
    1. 注意点①:クラスの静的(static)プロパティに状態を保持しない
    2. 注意点②:シングルトンクラスのコンストラクタにRequestやContainerを注入しない
    3. 注意点③:OctaneのFlushリスナーを活用する
  7. 本番環境運用のベストプラクティス
    1. 1. SupervisorによるOctaneの常駐・自動再起動設定
    2. 2. Nginxリバースプロキシ設定
    3. 3. デプロイスクリプトでのゼロダウンタイム反映
  8. Laravel Octaneを導入すべきケース・見送るべきケース
    1. 導入を強く推奨するケース
    2. 導入を見送る・慎重に検討すべきケース
  9. よくある質問(FAQ)
    1. Q. Laravel SailやDocker環境でもOctaneは動かせますか?
    2. Q. 既存のLaravelアプリに導入する際の安全な移行手順は?
    3. Q. PHP-FPMと比べてサーバーのメモリ消費量は増えますか?
  10. まとめ
  11. 関連記事

Laravel Octaneとは?なぜ劇的に高速化するのか

Laravel Octaneが圧倒的なパフォーマンスを発揮する最大の理由は、「リクエストごとのフレームワーク初期化(ブート処理)の排除」にあります。

従来のPHP-FPMとOctaneのライフサイクルの違い

従来のPHP-FPM(Webサーバー + PHP-FPM)とLaravel Octaneの処理フローを比較すると、その違いは一目瞭然です。

項目 従来のPHP-FPM Laravel Octane
フレームワークの起動 1リクエストごとにゼロからブート(設定・サービスプロバイダ・ルーティングの読込) サーバー起動時に1回だけブートし、メモリ上に保持
リクエスト処理 初期化 → ルーティング → コントローラ実行 → レスポンス → 全メモリ破棄 メモリ常駐のアプリインスタンスでコントローラ実行 → レスポンスのみ
レスポンス速度 数十ms 〜 数百ms(初期化オーバーヘッドが大きい) 数ms 〜 十数ms(純粋なロジック・DB処理時間のみ)
最大スループット 標準的(同時接続数に応じてCPU・I/O負荷増) 数倍〜十数倍のリクエスト/秒を処理可能

通常のLaravelアプリケーションでは、リクエスト全体の処理時間のうち30〜50%以上がフレームワーク自体のブート処理に費やされています。Octaneはこのオーバーヘッドを完全にスキップするため、特にJSON APIや高頻度アクセスのエンドポイントで絶大な効果を発揮します。

アプリケーション全体のパフォーマンス改善全般については、Laravelが遅い原因と解決策:パフォーマンスを最適化する方法でも詳しく解説しています。

3大アプリケーションサーバーの特徴と選び方(FrankenPHP / Swoole / RoadRunner)

Laravel Octaneは、PHPを実行する基盤として3種類のアプリケーションサーバーをサポートしています。それぞれの特徴・強み・導入難易度を理解し、プロジェクトの要件に適したものを選択しましょう。

項目 FrankenPHP(推奨) Swoole / Open Swoole RoadRunner
開発言語 / 基盤 Go言語 / Caddy Webサーバー C/C++(PECL拡張) Go言語(バイナリ常駐)
インストール難易度 ★☆☆(バイナリ自動DL・PECL不要) ★★★(PECL拡張のビルドが必要) ★☆☆(バイナリ自動DL・PECL不要)
HTTP/2・HTTP/3 標準対応(Caddy統合) 要リバースプロキシ 要リバースプロキシ
Early Hints / 圧縮 標準対応(Brotli / Zstandard) 非対応 非対応
並行タスク(Concurrent Tasks) 対応 対応(最高速) 対応
インメモリキャッシュ / テーブル 非対応(外部ストア推奨) 対応(Swoole Table) 非対応
おすすめ用途 迷ったらコレ(最新・モダン・導入が最も簡単) インメモリテーブルなどSwoole独自機能を使いたい場合 Go環境での安定稼働・実績重視の場合

どれを選ぶべきか?選び方の基準

  • 新規導入・一般的なプロジェクトFrankenPHP が第一選択です。Laravel公式でも現在標準として推奨されており、Caddyを内蔵しているためSSL自動更新やHTTP/3、Early Hintsなどの最新機能をそのまま利用できます。
  • 超高負荷な並行処理・インメモリテーブルを活用したい場合Swoole が適しています。Swoole Tableを利用したミリ秒未満のキャッシュや、タスクワーカーによる並行処理をフルに活用できます。
  • PHPプロセスとWebサーバーの分離を重視する場合RoadRunner が堅牢で安定した選択肢となります。

Laravel Octaneのインストールと初期セットアップ

ここからは、実際にLaravel環境へOctaneを導入する手順を解説します。Laravel 10、11、12、13の各バージョンに対応しています。

1. 前提条件の確認

  • PHP 8.2 以上(PHP 8.3 / 8.4 推奨)
  • PHPの pcntl 拡張が有効であること(CLI環境では通常標準有効)

2. Composerパッケージのインストール

まず、プロジェクトのルートディレクトリでOctaneパッケージを追加します。

composer require laravel/octane

3. octane:install コマンドの実行

次に、octane:install コマンドを実行して設定ファイルを生成し、サーバーバイナリをダウンロードします。--server オプションでサーバーを指定できます(省略した場合は対話形式で選択可能です)。

php artisan octane:install --server=frankenphp

FrankenPHPを指定した場合、必要なバイナリが自動的にダウンロードされ、プロジェクト直下に配置されます。

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

4. 設定ファイルと環境変数の確認

インストールが完了すると、config/octane.php が生成され、.env ファイルに以下の環境変数が自動追記されます。

OCTANE_SERVER=frankenphp

config/octane.php 内では、サーバーの種類、ワーカー数、最大リクエスト数、リクエストごとのフラッシュ処理(Listeners)などが詳細に定義されています。

// config/octane.php
'server' => env('OCTANE_SERVER', 'frankenphp'),

'max_execution_time' => 30,

Octaneサーバーの起動と基本コマンド

Octaneサーバーの起動・状態確認・再起動・停止を行うArtisanコマンドを確認しましょう。

サーバーの起動(octane:start)

サーバーを起動するには、octane:start コマンドを実行します。

php artisan octane:start --host=127.0.0.1 --port=8000 --workers=4

開発用の組込サーバーコマンド php artisan serve と異なり、Octaneは指定した複数のワーカープロセスを立ち上げて並行処理を行います。

ブラウザやcurlでアクセスすると、レスポンスヘッダーにサーバー情報が付与されて高速に応答します。

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

開発時のホットリロード(–watch)

Octaneはコードをメモリに保持するため、通常はファイルを編集しても再起動するまで変更が反映されません。開発中は --watch オプションを付けることで、ファイルの変更を検知して自動でワーカーを再読み込みできます。

事前にNode.jsパッケージの chokidar をインストールしておきます。

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

稼働確認・コード再読み込み・停止

コマンド 用途・動作
php artisan octane:status サーバーが稼働中かどうかを確認する
php artisan octane:reload ゼロダウンタイムでコードを再読込(ワーカープロセスを順次再起動)
php artisan octane:stop サーバープロセスを安全に停止する

特に php artisan octane:reload は、本番環境へのデプロイ時にサーバーを停止させずに最新コードへ切り替えるための重要コマンドです。

ワーカー数と最大リクエスト数のチューニング

  • ワーカー数(--workers: 既定ではサーバーのCPUコア数が自動設定されます。I/OバウンドなAPIではCPUコア数と同等〜2倍程度が目安です。
  • 最大リクエスト数(--max-requests: メモリリークを防ぐため、ワーカーが一定回数リクエストを処理したら自動でワーカープロセスを再起動します(既定: 500回)。
    php artisan octane:start --workers=4 --max-requests=1000

Octaneの高度な機能と活用例

1. 並行タスク処理(Octane::concurrently)

Octane::concurrently を使用すると、複数の処理を別々のタスクワーカーで同時に実行し、すべての結果が揃った時点で配列の分割代入でまとめて取得できます。

use App\Models\User;
use App\Models\Order;
use App\Services\ExternalPaymentApi;
use Laravel\Octane\Facades\Octane;

public function dashboard(ExternalPaymentApi $api): array
{
    // 3つの重い処理を並行して実行
    [$users, $recentOrders, $exchangeRates] = Octane::concurrently([
        fn () => User::query()->where('is_active', true)->count(),
        fn () => Order::query()->latest()->take(10)->get(),
        fn () => $api->fetchCurrentRates(),
    ]);

    return [
        'active_users' => $users,
        'recent_orders' => $recentOrders,
        'exchange_rates' => $exchangeRates,
    ];
}

直列実行では3つの処理の合計時間がかかりますが、concurrently を使えば最も時間のかかる処理1つ分の待ち時間でレスポンスを返せます。Laravel 11以降の並列処理全般についてはLaravelで実現する並列処理:効率的なタスク運用とパフォーマンス向上の方法も参考にしてください。

2. インメモリキャッシュ(Swoole Table)

Swoole環境では、共有メモリを利用した超高速なOctaneキャッシュドライバーが利用可能です。Redisなどの外部通信を伴わないため、極小のレイテンシーでキャッシュを読み書きできます。

use Illuminate\Support\Facades\Cache;

// 秒間数百万回のアクセスが可能なOctaneインメモリキャッシュ
Cache::store('octane')->put('system:announcement', '定期メンテナンスのお知らせ', 60);

$announcement = Cache::store('octane')->get('system:announcement');

※サーバー停止・再起動でメモリ内容は消去されるため、セッションや重要データの永続化ではなく、一時的な読み込み専用データやレートリミット用のカウンターに適しています。

導入時の必須注意点と状態汚染・メモリリーク防止策

Octaneを導入する上で最も重要なのが、メモリ常駐モデルによる「状態汚染(State Leaks)」と「メモリリーク」の回避です。

注意点①:クラスの静的(static)プロパティに状態を保持しない

staticプロパティにデータを追加すると、そのデータはリクエストが終了しても破棄されず、次の別ユーザーのリクエストでも残り続けます。これはメモリ肥大化だけでなく、他人のデータが漏洩する重大なセキュリティ事故に繋がります。

// ❌ 危険なアンチパターン(状態がリクエスト間で共有・蓄積される)
class CartManager
{
    public static array $items = [];

    public function addItem(int $productId): void
    {
        self::$items[] = $productId; // ユーザーAのデータがユーザーBのリクエストに残る!
    }
}
// ✅ 安全な改善パターン(リクエストごとに完結させる、またはDB/Sessionで管理)
class CartManager
{
    public function addItem(User $user, int $productId): void
    {
        $user->cartItems()->create(['product_id' => $productId]);
    }
}

注意点②:シングルトンクラスのコンストラクタにRequestやContainerを注入しない

サービスプロバイダで singleton として登録したクラスのコンストラクタで Request インスタンスを受け取ると、サーバー起動直後の最初のリクエスト情報が固定化され、2回目以降のリクエストでも初回のリクエストデータが参照されてしまいます。

// ❌ 危険なアンチパターン(シングルトンに初回のRequestが固定化される)
class TenantService
{
    public function __construct(protected Request $request)
    {
        // $this->request は最初のアクセス時のリクエストのまま更新されない
    }
}
// ✅ 安全な改善パターン(メソッドインジェクションまたはクロージャで都度解決する)
class TenantService
{
    // メソッドの引数で現在のRequestを受け取る
    public function getCurrentTenant(Request $request): ?Tenant
    {
        return Tenant::find($request->header('X-Tenant-ID'));
    }

    // または app() ヘルパー / コンテナから都度取得する
    public function getHeaderValue(): ?string
    {
        return request()->header('X-Tenant-ID');
    }
}

注意点③:OctaneのFlushリスナーを活用する

リクエスト終了時にクリーンアップが必要な独自サービスがある場合は、config/octane.phpflush 配列にリスナークラスを登録することで、リクエストごとに状態を確実にリセットできます。

// config/octane.php
'flush' => [
    App\Listeners\ResetCustomServiceState::class,
],

本番環境運用のベストプラクティス

本番サーバーでLaravel Octaneを運用する際は、プロセス監視ツール(Supervisor)リバースプロキシ(Nginx / Caddy)を組み合わせるのが標準的なアーキテクチャです。

1. SupervisorによるOctaneの常駐・自動再起動設定

サーバー障害や予期せぬクラッシュ時にOctaneを自動復旧させるため、Supervisorでプロセスを管理します。

設定ファイル例(/etc/supervisor/conf.d/octane.conf):

[program:laravel-octane]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/artisan octane:start --server=frankenphp --host=127.0.0.1 --port=8000 --workers=4 --max-requests=1000
autostart=true
autorestart=true
user=www-data
redirect_stderr=true
stdout_logfile=/var/www/html/storage/logs/octane-supervisor.log
stopwaitsecs=3600

設定を反映して起動します。

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-octane:*

バックグラウンド処理のワーカー監視については、queue:work — キューを実行するコマンドでも同様のSupervisor設定パターンを解説しています。

2. Nginxリバースプロキシ設定

Octaneの前段にNginxを配置し、画像・CSS・JSなどの静的アセットはNginxが直接配信し、PHPへの動的リクエストのみOctane(127.0.0.1:8000)へ転送します。

server {
    listen 80;
    server_name example.com;
    root /var/www/html/public;

    index index.php;
    charset utf-8;

    # 静的アセットはNginxが直接配信
    location / {
        try_files $uri $uri/ @octane;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    # 動的リクエストをOctaneへプロキシ転送
    location @octane {
        proxy_pass http://127.0.0.1:8000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

3. デプロイスクリプトでのゼロダウンタイム反映

CI/CDパイプラインやデプロイスクリプトの最後に octane:reload を組み込むことで、ダウンタイムなしで新しいソースコードを稼働中のワーカーへ適用できます。

# デプロイスクリプトの例
git pull origin main
composer install --no-dev --optimize-autoloader
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache

# Octaneワーカーのホットリロード
php artisan octane:reload

キャッシュの事前生成コマンドについては、config:cache — 設定ファイルをキャッシュするコマンドview:cache — ビューキャッシュを有効にするコマンドを参照してください。

Laravel Octaneを導入すべきケース・見送るべきケース

導入を強く推奨するケース

  • 高トラフィックなREST API / GraphQL API:毎秒多数のリクエストが発生し、レスポンス速度(数ms単位の削減)がUXやシステムコストに直結する環境。
  • マイクロサービス基盤:サービス間通信のレイテンシーを極限まで圧縮したい場合。
  • I/O待ちの多い集計・API連携処理Octane::concurrently を用いて複数処理を並行化したい場合。

導入を見送る・慎重に検討すべきケース

  • アクセス数が少なくボトルネックがDBにある場合:DBクエリが遅い(N+1問題やインデックス未設定)場合、Octaneを導入しても体感速度は改善しません。まずクエリ改善やキャッシュ導入を優先しましょう。
  • 古いサードパーティ製パッケージを多数利用している場合:メモリ常駐を想定していないステートフルな外部ライブラリがある場合、予期せぬデータ混入のリスクがあります。

よくある質問(FAQ)

Q. Laravel SailやDocker環境でもOctaneは動かせますか?

はい、完全に動作します。Laravel Sailを使用している場合は、sail artisan octane:install を実行し、docker-compose.yml の起動コマンド(entrypoint / command)を php artisan octane:start に変更するだけで簡単にコンテナ環境で利用できます。

Q. 既存のLaravelアプリに導入する際の安全な移行手順は?

まずローカル環境で php artisan octane:start を起動し、静的プロパティやシングルトンでの状態保持がないかコードレビューを行います。次にステージング環境で負荷テスト(Apache Benchやk6など)を実施し、メモリ使用量が右肩上がりに増え続けないか(メモリリークがないか)を確認してから本番環境へ導入するのが安全です。

Q. PHP-FPMと比べてサーバーのメモリ消費量は増えますか?

はい。各ワーカープロセスがLaravelフレームワーク全体をメモリ上に保持し続けるため、常時一定のメモリ(ワーカー1つあたり数十MB〜100MB程度)を消費します。十分なRAM容量を確保したサーバーを選定してください。

まとめ

Laravel Octaneは、FrankenPHP・Swoole・RoadRunnerといった高性能サーバーを活用し、アプリケーションをメモリ常駐させることでPHP-FPMの限界を超えたスループットと圧倒的なレスポンス速度を実現する公式パッケージです。

  • 対応サーバー:手軽さとモダンな機能性を求めるなら FrankenPHP、極限の並行性と独自インメモリテーブルを求めるなら Swoole がおすすめ。
  • 運用上の重要点:static変数やシングルトンによる状態汚染(State Leaks)を避け、本番では Supervisor + Nginx + octane:reload で安定稼働させる。

Artisanコマンド全般の活用法はLaravelのArtisanコマンド徹底解説|最速チートシート&現場ノウハウでも網羅しています。ぜひOctaneを活用して、高速でスケーラブルなLaravelアプリケーションを構築してみてください。

レン (Wren)

こんにちは。レンです。

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

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

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

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

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

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

コメント