Встановлення
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:
docker pull ghcr.io/oxphp/oxphp:0.13.0Образ містить:
- Бінарний файл сервера OxPHP — асинхронний HTTP-сервер
- Середовище виконання PHP ZTS — 8.4 або 8.5 залежно від завантаженого тегу; потокобезпечний PHP для виконання в кількох воркерах
- PHP-розширення OxPHP (
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; 33 в образі Debian) створено заздалегідь, а власником/var/www/htmlйого призначено під час збирання. Щоб задати конкретний 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 у ті ночі, коли гілка змінилася після останнього повністю успішного запуску, і не дають жодних гарантій стабільності. Якщо вночі збірка Debian завершується невдачею, :nightly-trixie і :php<minor>-nightly-trixie лишаються на останній успішній збірці, тож можуть відставати від :nightly.
Образ Debian витрачає менше CPU на запит, і на це є дві причини:
- Локальне сховище потоку (thread-local storage). Потокобезпечний PHP звертається до стану рушія кожного потоку через локальний для потоку вказівник. У збірці під musl PHP лишає цей вказівник на моделі TLS global-dynamic, тож код у
libphp.soдістається до нього через виклик у середовище виконання TLS; під glibc використовується initial-exec — завантаження відносно вказівника потоку. - Алокатор. Алокатор musl, яким поряд із власним менеджером пам’яті PHP користуються розширення та бібліотеки на кшталт libpq, відображає свіжу пам’ять під результати запитів libpq і скасовує це відображення, коли їх звільняють. На x86-64 це коштує скидань TLB (TLB shootdown) на всіх потоках сервера.
Процесорний час контейнера OxPHP на одну відповідь, образ Debian порівняно з образом Alpine, за тієї самої ревізії OxPHP і того самого патч-релізу PHP 8.5: застосунок Yii3 під wrk -c64, медіана шести поперемінних запусків. Кожен рядок виміряно на одному хості: x86-64 — на хмарній віртуальній машині з 16 vCPU (AMD EPYC 9575F), arm64 — у Docker Desktop на Apple silicon. Власний процесорний час Postgres не враховано.
| Сторінка 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: наприклад,libicu-devіlibpq-devдля збиранняintlіpdo_pgsql, аlibicu76іlibpq5— під час виконання. - Збирайте розширення в етапі
php:<minor>-zts-trixie..so, зібраний під musl в етапі-zts-alpine, несумісний із цим образом, і навпаки. www-dataмає UID/GID 33, а не 82:securityContext.runAsUser: 33, і все, чому власника призначають за номером, має використовувати 33.wgetнемає, але єcurl. Перевірка працездатності, написана для образу Alpine якwget --spider http://localhost:9090/health, перетворюється наcurl -fsS -o /dev/null http://localhost:9090/health.- Образ більший: базовий образ PHP у стиснутому вигляді займає близько 170–180 MiB проти приблизно 45–50 MiB для Alpine.
Структура образу
Розташування файлів в образі середовища виконання:
/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Значення <ABI> залежить від мінорної версії PHP. PHP 8.4 використовує 20240924, PHP 8.5 — 20250925. У наведених нижче прикладах закріплено 20250925, бо їхній рядок FROM вказує на php:8.5-zts-alpine3.23 (PHP типового тегу :0.13.0) — змінивши FROM, ви маєте змінити й дату. Щоб визначити її переносно під час збирання:
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 (крім conf.d/, у /usr/local/etc/php/ лежать лише зразки php.ini-development і php.ini-production з апстриму, і PHP не завантажує жоден із них), а також жодних налаштувань застосунку. Додайте свої як файл .ini у conf.d, змонтувавши або скопіювавши його; див. посібник з Docker.
Імʼя файлу визначає, чи буде .ini прочитано і коли. PHP розбирає всі файли .ini у conf.d в алфавітному порядку й мовчки пропускає файли з будь-якими іншими іменами. Для звичайного параметра перемагає останнє прочитане значення, тож файл, що його перевизначає, має йти за алфавітом після файлу, який його задає. Натомість extension= і zend_extension= збираються з усіх файлів і завантажуються всі, тож пізніший extension= ніколи не замінює попередній.
Три компоненти OxPHP та їхнє призначення; розміри виміряно в образі 0.11.0. Розміри відрізняються для linux/amd64 і linux/arm64 та змінюються від релізу до релізу:
| Компонент | Розмір | Призначення |
|---|---|---|
oxphp |
~12–15 МБ | HTTP-сервер, маршрутизація, плагіни, метрики |
liboxphp_bridge.so |
~150–170 КБ | Спільна бібліотека-міст, що звʼязує сервер із середовищем виконання PHP |
oxphp_sapi.so |
~700 КБ | 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 і всі його залежності. Мінорна версія PHP у вашому FROM має збігатися з тегом OxPHP, з якого ви копіюєте, і бібліотека C теж: артефакти з тегу -trixie ставляться на php:<minor>-zts-trixie, а не на базовий образ Alpine. Вам достатньо скопіювати три артефакти OxPHP і додати libgcc, з яким компонується зібраний на Rust бінарний файл oxphp і якого немає в образі PHP на Alpine:
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. Додайте їх самостійно через COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer і pecl install xdebug, як це робить ціль dev у посібнику з Docker.
Production Dockerfile
Офіційний образ OxPHP зберігає PHP CLI та інструменти для розширень (php, phpize, pecl, docker-php-ext-install) образу php:<minor>-zts-alpine3.23, на якому його зібрано, тож розширення можна встановлювати безпосередньо в ньому; див. Встановлення розширень PHP у продакшні. Якщо натомість збирати їх в окремому етапі, пакети, потрібні лише для збирання, як-от icu-dev, не потрапляють до фінального образу. Те, чи потрібні вам додаткові PHP-розширення, визначає, який із двох варіантів збирання обрати.
Якщо вашому застосунку потрібні додаткові розширення (pdo_mysql, intl тощо), зберіть їх в окремому етапі й скопіюйте до фінального образу:
# 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Якщо вашому застосунку додаткові розширення не потрібні, цього достатньо:
FROM ghcr.io/oxphp/oxphp:0.13.0
COPY --chown=www-data:www-data . /var/www/html/publicЗберіть і запустіть:
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)
Зберіть OxPHP з вихідного коду з вимкненою функцією PHP, щоб обслуговувати лише статичні файли:
cargo build --release --no-default-featuresБінарний файл буде в target/release/oxphp. Він використовує виконавця-заглушку, який повертає на PHP-запити відповідь-заповнювач, а статичні файли обслуговує як зазвичай. Цей режим корисний, щоб тестувати сервер без середовища виконання PHP.
Збирання з вихідного коду (з PHP)
Для збирання OxPHP з повною підтримкою PHP спершу потрібно скомпілювати та встановити бібліотеку-міст і PHP-розширення.
Передумови
- Інструментарій Rust (1.91.1 або новіший)
- PHP 8.4 або 8.5 з увімкненим ZTS (Zend Thread Safety)
- Компілятор C (gcc або clang)
phpizeі заголовкові файли PHP для розробки
Кроки збирання
-
Зберіть і встановіть бібліотеку-міст.
cd ext/bridge make && sudo make install -
Зберіть і встановіть PHP-розширення.
cd ../ phpize && ./configure --enable-oxphp-sapi && make && sudo make install -
Зберіть OxPHP. Типові функції включають php.
cargo build --release
Під час виконання бінарному файлу потрібні спільні бібліотеки на шляху пошуку бібліотек:
export LD_LIBRARY_PATH=/usr/local/lib
./target/release/oxphpДля розгортання на Alpine Linux збирайте в тому самому образі php:{8.4,8.5}-zts-alpine, що використовується для середовища виконання PHP, — з тією ж мінорною версією, що й образ OxPHP, який ви постачаєте. Змішування збірок під glibc і musl спричиняє помилки під час виконання. Офіційний Docker-образ розвʼязує це правильно.
Перевірка встановлення
Після запуску OxPHP структурований JSON-журнал підтверджує, що сервер працює:
{"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"}Перевірте, що сервер відповідає:
curl http://localhost/Якщо ви ввімкнули внутрішній сервер через INTERNAL_ADDR, перевірте ендпоінт стану:
curl http://localhost:9090/healthСправний сервер повертає 200 зі статусом у JSON. Сервер у деградованому стані повертає 503.
Що далі
- Швидкий старт — створіть проєкт, запустіть OxPHP через Docker Compose і надішліть перший запит
- Посібник з Docker — Dockerfile для розробки та production, конфігурація Compose і монтування томів
- Налаштування — повний довідник змінних середовища