インストール

OxPHP は Docker イメージとして配布されており、PHP アプリケーションの配信を始めるうえで最速かつ推奨される方法です。このイメージには、サーバーバイナリ、PHP 8.4 または 8.5 ZTS、OxPHP 拡張、そして Alpine Linux 上のすべてのランタイム依存関係が同梱されています。デフォルトの :0.13.0 および :latest タグには PHP 8.5 が含まれます。PHP 8.4 を取得するには、:0.13.0-php8.4、:php8.4、または任意の *-php8.4* タグバリアントを使用してください。

Docker(推奨)

GitHub Container Registry から公式イメージを取得します。

bash
docker pull ghcr.io/oxphp/oxphp:0.13.0

このイメージには以下が含まれます。

  • OxPHP サーバーバイナリ — 非同期 HTTP サーバー
  • PHP ZTS ランタイム — 取得したタグに応じて 8.4 または 8.5。マルチワーカー実行のためのスレッドセーフな PHP
  • OxPHP PHP 拡張(oxphp_sapi.so) — oxphp_request_id()、oxphp_server_info()、oxphp_worker() などの組み込み関数を提供します
  • ブリッジライブラリ(liboxphp_bridge.so) — Rust サーバーと PHP ランタイムを接続します
  • Alpine Linux ベース — 最小限のランタイムフットプリント(Debian ビルドはナイトリーで公開されています。Debian(glibc)イメージを参照)
  • USER ディレクティブなし — このイメージは特権ポートをバインドできるように root として 起動 します(nginx:alpine / php-fpm:alpine / frankenphp:alpine と同様)。ただし oxphp serve/run は配信を開始する前にデフォルトで www-data へ降格するため、トラフィックが最初から root として処理されることはありません。www-data ユーザー(UID 82、GID 82。Debian イメージでは 33)はあらかじめ作成されており、ビルド時に /var/www/html の所有者がこのユーザーに変更されます。特定の uid を指定したい場合や多層防御を強化したい場合は、オーケストレーターのレベルでランタイムの実行 ID を明示的に固定してください。
    • docker run --user www-data ghcr.io/oxphp/oxphp:0.13.0
    • Compose: services.app.user: www-data
    • Kubernetes: securityContext.runAsUser: 82

Debian(glibc)イメージ

ナイトリーのパイプラインでは、同じサーバーを Alpine ではなく Debian trixie 上でビルドしたものも公開しています。タグは ghcr.io/oxphp/oxphp:nightly-trixie(PHP 8.4)、:php8.4-nightly-trixie、:php8.5-nightly-trixie で、linux/amd64 と linux/arm64 向けに提供されます。

ナイトリーのみ

タグ付きリリースは Alpine のみです。ナイトリータグは、前回の完全に成功した実行以降に main が進んだ夜に main からビルドされ、安定性の保証はありません。Debian のビルドが失敗した夜には、:nightly-trixie と :php<minor>-nightly-trixie は最後に成功したビルドのまま残るため、:nightly より遅れることがあります。

Debian イメージは、次の 2 つの理由により、リクエストあたりの CPU 消費が少なくなります。

  • スレッドローカルストレージ。 スレッドセーフな PHP は、スレッドローカルなポインターを介してエンジンのスレッドごとの状態にアクセスします。musl に対してビルドされた PHP はそのポインターを global-dynamic TLS モデルのままにするため、libphp.so 内のコードは TLS ランタイムの呼び出しを通じてそれにアクセスします。glibc に対しては initial-exec を使い、スレッドポインターからの相対ロードで済みます。
  • アロケーター。 musl のアロケーターは、PHP 自身のメモリマネージャーとは別に、拡張や libpq などのライブラリが使用するものです。これは libpq のクエリ結果のために新しいメモリをマップし、解放時にアンマップします。x86-64 では、これがサーバーのスレッド全体にわたる TLB シュートダウンのコストになります。

レスポンスあたりの OxPHP コンテナの CPU 時間を、同じ OxPHP リビジョンと PHP 8.5 パッチのもとで Debian イメージと Alpine イメージで比較したものです。対象は wrk -c64 で負荷をかけた Yii3 アプリケーションで、交互に行った 6 回の実行の中央値です。各行は 1 つのホストで計測しました。x86-64 は 16 vCPU のクラウド VM(AMD EPYC 9575F)、arm64 は Apple シリコン上の Docker Desktop です。Postgres 自身の CPU は含まれていません。

Yii3 のページ Postgres を読み込むページ
x86-64、従来モード −18.9% −14.1%
x86-64、ワーカーモード −18.1% −18.6%
arm64、従来モード −8.5% −9.0%

これをベースにビルドする Dockerfile で変わる点:

  • パッケージは apk ではなく apt-get update && apt-get install -y --no-install-recommends で、Debian のパッケージ名で導入します。たとえば intl と pdo_pgsql のビルドには libicu-dev と libpq-dev、ランタイムには libicu76 と libpq5 を使います。
  • 拡張は php:<minor>-zts-trixie ステージでビルドします。-zts-alpine ステージで musl に対してビルドされた .so はこのイメージと互換性がなく、その逆も同様です。
  • www-data の UID/GID は 82 ではなく 33 です。securityContext.runAsUser: 33 とし、数値で chown しているものはすべて 33 を使う必要があります。
  • wget はありませんが、curl はあります。Alpine イメージ向けに wget --spider http://localhost:9090/health と書いたヘルスチェックは、curl -fsS -o /dev/null http://localhost:9090/health になります。
  • イメージは大きくなります。PHP ベースは圧縮時で約 170〜180 MiB あり、Alpine の約 45〜50 MiB を上回ります。

イメージ構造

ランタイムイメージのファイルレイアウト:

text
/usr/local/ ├── bin/ │ └── oxphp # server binary ├── lib/ │ ├── libphp.so # PHP ZTS runtime (8.4 or 8.5, matches the image tag) │ ├── liboxphp_bridge.so # C bridge library │ └── php/extensions/no-debug-zts-<ABI>/ │ ├── oxphp_sapi.so # OxPHP PHP extension │ └── sodium.so, ... # from the PHP base image; the set depends on the tag └── etc/php/ └── conf.d/ ├── docker-php-ext-*.ini # from the PHP base image; the set depends on the tag └── extension.ini # extension=oxphp_sapi.so
Note

<ABI> の値は PHP のマイナーバージョンによって異なります。 PHP 8.4 は 20240924 を使用し、PHP 8.5 は 20250925 を使用します。以下の例が 20250925 を固定しているのは、FROM 行がデフォルトの :0.13.0 タグの PHP である php:8.5-zts-alpine3.23 を対象としているためです。FROM を切り替える場合は、日付も切り替える必要があります。ビルド内で移植性のある形で導出するには:

bash
php -r 'echo ini_get("extension_dir");' # /usr/local/lib/php/extensions/no-debug-zts-20250925

ハードコーディングを避けるため、シェルコマンド内では $(php -r 'echo ini_get("extension_dir");') を使用してください。

このイメージには独自の php.ini は含まれておらず(/usr/local/etc/php/ には conf.d/ のほか、アップストリームのサンプルである php.ini-development と php.ini-production があるだけで、PHP はどちらも読み込みません)、アプリケーション向けの設定も入っていません。設定は conf.d 配下の .ini ファイルとして、マウントするかコピーして用意してください。Docker ガイド を参照してください。

Note

.ini が読み込まれるかどうか、またいつ読み込まれるかはファイル名で決まります。PHP は conf.d 内のすべての .ini ファイルをアルファベット順に解析し、それ以外の名前のファイルは何も通知せずにスキップします。通常の設定では最後に読み込まれた値が有効になるため、設定を上書きするファイルは、その設定を定義するファイルより後ろにソートされる名前にする必要があります。一方、extension= と zend_extension= はすべてのファイルから収集されてすべて読み込まれるため、後の extension= が前のものを置き換えることはありません。

OxPHP の 3 つのコンポーネントとその目的です。サイズは 0.11.0 イメージで計測したものです。サイズは linux/amd64 と linux/arm64 で異なり、リリースごとにも変わります。

コンポーネント サイズ 目的
oxphp 約 12〜15 MB HTTP サーバー、ルーティング、プラグイン、メトリクス
liboxphp_bridge.so 約 150〜170 KB サーバーを PHP ランタイムに接続する共有ブリッジライブラリ
oxphp_sapi.so 約 700 KB PHP 関数(oxphp_request_id()、OxPHP\Http\Request など)

依存関係チェーン:

graph LR
  oxphp["oxphp"] --> libphp["libphp.so"]
  libphp --> deps["libxml2, libcurl, libsqlite3, libonig, ..."]
  oxphp --> bridge["liboxphp_bridge.so"]
  sapi["oxphp_sapi.so"] --> bridge

oxphp バイナリは libphp.so と liboxphp_bridge.so にリンクします。PHP 拡張 oxphp_sapi.so もブリッジライブラリにリンクしており、これによりリクエストごとの状態が PHP コードから利用できるようになります。

最小構成の Dockerfile

ベースイメージ php:8.5-zts-alpine3.23(または php:8.4-zts-alpine3.23)には、libphp.so とそのすべての依存関係がすでに含まれています。FROM の PHP マイナーバージョンは、コピー元の OxPHP タグに合わせてください。C ライブラリも同様で、-trixie タグの成果物は Alpine ベースではなく php:<minor>-zts-trixie に載せます。必要なのは、3 つの OxPHP 成果物をコピーし、libgcc を追加することだけです。libgcc は Rust でビルドされた oxphp バイナリがリンクしているライブラリで、Alpine の PHP イメージには含まれていません。

Dockerfile
FROM php:8.5-zts-alpine3.23 RUN apk add --no-cache libgcc COPY --from=ghcr.io/oxphp/oxphp:0.13.0 /usr/local/bin/oxphp /usr/local/bin/oxphp COPY --from=ghcr.io/oxphp/oxphp:0.13.0 /usr/local/lib/liboxphp_bridge.so /usr/local/lib/ COPY --from=ghcr.io/oxphp/oxphp:0.13.0 /usr/local/lib/php/extensions/no-debug-zts-20250925/oxphp_sapi.so /usr/local/lib/php/extensions/no-debug-zts-20250925/ RUN echo "extension=oxphp_sapi.so" > /usr/local/etc/php/conf.d/oxphp.ini COPY --chown=www-data:www-data . /var/www/html/public EXPOSE 80 443 CMD ["oxphp"]

この方法は開発に便利です。PHP CLI、docker-php-ext-install、pecl がすべて利用できます。Composer と Xdebug は PHP ベースイメージには含まれていません。Docker ガイド の dev ターゲットと同様に、COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer と pecl install xdebug で自分で追加してください。

本番用の Dockerfile

公式の OxPHP イメージは、ベースとなっている php:<minor>-zts-alpine3.23 イメージの PHP CLI と拡張ツール(php、phpize、pecl、docker-php-ext-install)を保持しているため、その中で直接拡張をインストールできます。本番環境での PHP 拡張機能のインストールを参照してください。代わりに別のステージで拡張をビルドすれば、icu-dev のようなビルド専用のパッケージを最終イメージから除外できます。追加の PHP 拡張が必要かどうかによって、次の 2 つのビルドのどちらを選ぶかが決まります。

アプリケーションが追加の拡張(pdo_mysql、intl など)を必要とする場合は、別のステージでビルドし、最終イメージにコピーします。

Dockerfile
# Extension build stage FROM php:8.5-zts-alpine3.23 AS extensions RUN apk add --no-cache icu-dev postgresql-dev \ && docker-php-ext-install pdo pdo_mysql pdo_pgsql intl # Production FROM ghcr.io/oxphp/oxphp:0.13.0 # Runtime dependencies for extensions USER root RUN apk add --no-cache icu-libs libpq # Copy compiled extensions COPY --from=extensions /usr/local/lib/php/extensions/no-debug-zts-20250925/*.so /usr/local/lib/php/extensions/no-debug-zts-20250925/ # Enable extensions RUN { \ echo "extension=pdo.so"; \ echo "extension=pdo_mysql.so"; \ echo "extension=pdo_pgsql.so"; \ echo "extension=intl.so"; \ } > /usr/local/etc/php/conf.d/app-extensions.ini USER www-data COPY --chown=www-data:www-data . /var/www/html/public

ビルドして実行します。

bash
docker build -t my-app . docker run -p 80:80 my-app

サーバーはデフォルトでポート 80 をリッスンします。ドキュメントルートは /var/www/html/public で、上記のスニペットはプロジェクトをそこへ直接コピーしています。すでに public/ サブディレクトリを持つ Laravel、Symfony、その他のフレームワークでは、代わりに COPY --chown=www-data:www-data . /var/www/html を使用し、フレームワーク自身の public/ がデフォルトと一致するようにしてください。構成がさらに異なる場合は、DOCUMENT_ROOT 環境変数でドキュメントルートを上書きしてください。

ソースビルド(PHP なし)

PHP 機能を無効にして OxPHP をソースからビルドすると、静的ファイルのみを配信できます。

bash
cargo build --release --no-default-features

バイナリは target/release/oxphp にあります。このモードでは、静的ファイルは通常どおり配信しつつ、PHP リクエストにはプレースホルダーレスポンスを返すスタブエグゼキュータが使用されます。PHP ランタイムが存在しない状態でサーバーをテストするのに便利です。

ソースビルド(PHP あり)

完全な PHP サポートを備えた OxPHP をビルドするには、まずブリッジライブラリと PHP 拡張をコンパイルしてインストールする必要があります。

前提条件

  • Rust ツールチェーン(1.91.1 以降)
  • ZTS(Zend Thread Safety)を有効にした PHP 8.4 または 8.5
  • C コンパイラ(gcc または clang)
  • phpize と PHP 開発ヘッダー

ビルド手順

  1. ブリッジライブラリをビルドしてインストールします。

    bash
    cd ext/bridge make && sudo make install
  2. PHP 拡張をビルドしてインストールします。

    bash
    cd ../ phpize && ./configure --enable-oxphp-sapi && make && sudo make install
  3. OxPHP をビルドします。 デフォルトの機能には php が含まれます。

    bash
    cargo build --release

このバイナリは、実行時にライブラリ検索パス上の共有ライブラリを必要とします。

bash
export LD_LIBRARY_PATH=/usr/local/lib ./target/release/oxphp
Note

Alpine Linux にデプロイする場合は、PHP ランタイムに使用するのと同じ php:{8.4,8.5}-zts-alpine イメージ内でビルドしてください。出荷する OxPHP イメージのマイナーバージョンに合わせます。glibc と musl のビルドを混在させると、実行時エラーが発生します。公式の Docker イメージはこれを正しく処理します。

インストールの確認

OxPHP を起動すると、構造化された JSON ログ出力によってサーバーが稼働していることを確認できます。

text
{"timestamp":"...","level":"INFO","message":"OxPHP HTTP server starting","listen_addr":"0.0.0.0:80",...} {"timestamp":"...","level":"INFO","message":"Server listening","addr":"0.0.0.0:80"}

サーバーが応答することをテストします。

bash
curl http://localhost/

INTERNAL_ADDR で内部サーバーを有効にした場合は、ヘルスエンドポイントを確認します。

bash
curl http://localhost:9090/health

正常なサーバーは 200 と JSON ステータスを返します。劣化したサーバーは 503 を返します。

次のステップ

  • クイックスタート — プロジェクトを作成し、Docker Compose で OxPHP を実行して、最初のリクエストを送ります
  • Docker ガイド — 開発用と本番用の Dockerfile、Compose の設定、ボリュームマウント
  • 設定 — 環境変数の完全なリファレンス