安装

OxPHP 以 Docker 镜像的形式分发,这是开始为 PHP 应用提供服务最快、也最推荐的方式。该镜像在 Alpine Linux 上打包了服务器二进制文件、PHP 8.4 或 8.5 ZTS、OxPHP 扩展以及全部运行时依赖。默认的 :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 已 chown 给它。如需指定特定 uid 或额外的纵深防御,请在编排层显式固定运行时身份:
    • docker run --user www-data ghcr.io/oxphp/oxphp:0.13.0
    • Compose:services.app.user: www-data
    • Kubernetes:securityContext.runAsUser: 82

Debian(glibc)镜像

每夜构建流水线还会发布同一个服务器基于 Debian trixie(而非 Alpine)构建的版本: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 镜像处理每个请求消耗的 CPU 更少,原因有二:

  • 线程局部存储。 线程安全的 PHP 通过一个线程局部指针访问引擎的每线程状态。基于 musl 构建时,PHP 让该指针停留在 global-dynamic TLS 模型上,因此 libphp.so 中的代码要通过调用 TLS 运行时才能访问它;基于 glibc 时则使用 initial-exec,即一次相对于线程指针的加载。
  • 内存分配器。 扩展以及 libpq 之类的库会在 PHP 自身的内存管理器之外使用 musl 的分配器,它会为 libpq 的查询结果映射新的内存,并在这些结果被释放时解除映射。在 x86-64 上,这会在服务器的各个线程之间引发 TLB shootdown。

下表是 OxPHP 容器每个响应的 CPU 时间,Debian 镜像对比 Alpine 镜像,OxPHP 修订版和 PHP 8.5 补丁版本均相同:一个 Yii3 应用,在 wrk -c64 下运行,取六次交替运行的中位数。每一行都在同一台主机上测得:x86-64 在一台 16 vCPU 的云虚拟机(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 需要做出以下改变:

  • 软件包通过 apt-get update && apt-get install -y --no-install-recommends 安装,而不是 apk,并且使用 Debian 的包名:例如构建 intl 和 pdo_pgsql 需要 libicu-dev 和 libpq-dev,运行时需要 libicu76 和 libpq5。
  • 在 php:<minor>-zts-trixie 阶段中构建扩展。在 -zts-alpine 阶段中基于 musl 构建的 .so 与该镜像不兼容,反之亦然。
  • www-data 的 UID/GID 是 33,而不是 82: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 行以 php:8.5-zts-alpine3.23 为目标,即默认的 :0.13.0 标签所用的 PHP —— 一旦切换 FROM,就必须同时切换该日期。若要在构建过程中可移植地推导出它:

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

在 shell 命令中使用 $(php -r 'echo ini_get("extension_dir");'),以避免硬编码。

镜像本身不带 php.ini(除 conf.d/ 外,/usr/local/etc/php/ 中只有上游的 php.ini-development 和 php.ini-production 示例文件,PHP 两者都不会加载),也不带任何应用设置。请将你自己的设置作为 .ini 文件放到 conf.d 下,通过挂载或复制的方式提供;参见 Docker 指南。

Note

文件名决定了 .ini 是否被读取以及何时被读取。PHP 按字母顺序解析 conf.d 中的每个 .ini 文件,并静默跳过任何其他名称的文件。对于普通设置,最后读取到的值生效,因此用于覆盖某个设置的文件,其名称必须排在设置该值的文件之后。extension= 和 zend_extension= 则不同:它们会从每个文件中收集并全部加载,因此后读取的 extension= 永远不会替换先前的那个。

OxPHP 的三个组件及其用途,大小在 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 标签的构件应放到 php:<minor>-zts-trixie 上,而不是 Alpine 基础镜像上。你只需复制三个 OxPHP 构件,并添加 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 扩展,决定了应采用以下两种构建方式中的哪一种。

如果你的应用需要额外的扩展(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,上面的代码片段直接将项目复制到其中。对于 Laravel、Symfony 或其他本身就带有 public/ 子目录的框架,请改用 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。它使用一个桩执行器(stub executor),对 PHP 请求返回占位响应,同时正常提供静态文件服务。这种模式适合在没有 PHP 运行时的情况下测试服务器。

源码构建(含 PHP)

构建具备完整 PHP 支持的 OxPHP,需要先编译并安装桥接库和 PHP 扩展。

前置条件

  • Rust 工具链(1.91.1 或更高版本)
  • 启用了 ZTS(Zend Thread Safety,Zend 线程安全)的 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 配置以及卷挂载
  • 配置 —— 完整的环境变量参考
发现错误?报告问题 →