Magento на OxPHP

Magento — самый тяжёлый рецепт в этом разделе. Он требует поисковый движок (OpenSearch), длинный список расширений и шаг развёртывания статического контента. Он работает в режиме framework-маршрутизации OxPHP с pub/ в качестве корня документов, но его версионированные URL статических ресурсов требуют одного дополнительного шага, описанного ниже.

Стек вкратце

  • Образ OxPHP: ghcr.io/oxphp/oxphp:0.10.0-php8.4-alpine3.23 (PHP 8.4)
  • Режим маршрутизации: Framework (ENTRY_FILE=index.php; DOCUMENT_ROOT=/var/www/html/pub переопределяет стандартный …/public)
  • Добавленные расширения: bcmath, gd, intl, pdo_mysql, soap, xsl, zip, mbstring, ftp, pcntl, sockets
  • Сервисы: OxPHP + MySQL 8.0 + OpenSearch 2.x
  • URL: http://localhost:8093 · админка /admin · внутренний http://localhost:9094/health
Версия PHP

Magento 2.4.8 объявляет "php": "~8.2 || ~8.3 || ~8.4" и отклоняет PHP 8.5, поэтому зафиксируйте образ на PHP 8.4. ext-sockets — транзитивная зависимость (php-amqplib), и для её компиляции нужны linux-headers.

Структура проекта

Magento Open Source из официального канала распространения требует ключи авторизации Adobe Marketplace. Чтобы установить без ключей, клонируйте репозиторий с открытым исходным кодом (его модули поставляются прямо в дереве через replace, поэтому composer install подтягивает только зависимости с Packagist):

bash
mkdir -p magento-oxphp git clone --branch 2.4.8 --depth 1 https://github.com/magento/magento2.git magento-oxphp/src # composer install runs later, inside the PHP 8.4 container (composer:2 is PHP 8.5 # and Magento rejects it): docker compose run --rm --no-deps -e COMPOSER_MEMORY_LIMIT=-1 app \ composer install --no-interaction --prefer-dist

Dockerfile и compose-файл

src/Dockerfile.oxphp назван так, чтобы не конфликтовать с собственными docker-ресурсами Magento.

src/Dockerfile.oxphp
ARG OXPHP_VERSION=0.10.0 ARG PHP_VERSION=8.4 ARG ALPINE_VERSION=3.23 # ── PHP base: Magento runtime extensions ────────────────────── FROM php:${PHP_VERSION}-zts-alpine${ALPINE_VERSION} AS php-base RUN apk add --no-cache \ icu-libs libpng libjpeg-turbo freetype oniguruma libzip libxslt \ && apk add --no-cache --virtual .build-deps \ icu-dev libpng-dev libjpeg-turbo-dev freetype-dev oniguruma-dev \ libzip-dev libxslt-dev libxml2-dev linux-headers \ && docker-php-ext-configure gd --with-jpeg --with-freetype \ && docker-php-ext-install -j"$(nproc)" \ bcmath gd intl pdo_mysql soap xsl zip mbstring ftp pcntl sockets \ && apk del .build-deps # ── Composer ────────────────────────────────────────────────── FROM composer:2 AS composer # ── OxPHP artifacts (PHP 8.4 image) ─────────────────────────── FROM ghcr.io/oxphp/oxphp:${OXPHP_VERSION}-php${PHP_VERSION}-alpine${ALPINE_VERSION} AS oxphp # ── dev: OxPHP server + PHP CLI + Composer + Magento extensions ─ FROM php-base AS dev RUN apk add --no-cache libgcc git patch COPY --from=composer /usr/bin/composer /usr/local/bin/composer COPY --from=oxphp /usr/local/bin/oxphp /usr/local/bin/oxphp COPY --from=oxphp /usr/local/lib/liboxphp_bridge.so /usr/local/lib/ COPY --from=oxphp /usr/local/lib/php/extensions/ /tmp/oxphp-ext/ RUN cp /tmp/oxphp-ext/*/oxphp_sapi.so "$(php -r 'echo ini_get("extension_dir");')/" \ && rm -rf /tmp/oxphp-ext \ && echo "extension=oxphp_sapi.so" > /usr/local/etc/php/conf.d/oxphp-ext.ini RUN { \ echo "[opcache]"; echo "opcache.enable=1"; echo "opcache.enable_cli=1"; \ echo "opcache.validate_timestamps=1"; echo "opcache.revalidate_freq=0"; \ } > /usr/local/etc/php/conf.d/opcache-dev.ini RUN { \ echo "memory_limit=4G"; echo "max_execution_time=1800"; \ echo "realpath_cache_size=10M"; echo "realpath_cache_ttl=86400"; \ echo "upload_max_filesize=64M"; echo "post_max_size=64M"; \ } > /usr/local/etc/php/conf.d/magento.ini RUN getent passwd www-data >/dev/null \ || adduser -D -H -u 82 -G www-data -s /sbin/nologin www-data RUN mkdir -p /var/www/html/pub && chown -R www-data:www-data /var/www/html ENV LD_LIBRARY_PATH=/usr/local/lib WORKDIR /var/www/html EXPOSE 80 9090 CMD ["oxphp"]

Установка и первый запуск

bash
docker compose up -d db opensearch # composer install (see Project layout), then: docker compose run --rm app php bin/magento setup:install \ --base-url=http://localhost:8093/ \ --db-host=db --db-name=magento --db-user=magento --db-password=magento \ --admin-firstname=Admin --admin-lastname=User \ --admin-email=admin@example.com --admin-user=admin --admin-password='Admin123!' \ --language=en_US --currency=USD --timezone=America/New_York \ --search-engine=opensearch --opensearch-host=opensearch --opensearch-port=9200 \ --opensearch-index-prefix=magento --opensearch-enable-auth=0 # production mode compiles DI and deploys static content docker compose run --rm app php bin/magento deploy:mode:set production # CRITICAL for OxPHP: make versioned static URLs resolve (see notes below) docker compose run --rm app sh -c \ 'ln -sfn . "pub/static/version$(cat pub/static/deployed_version.txt)"' docker compose up -d app

Заметки по OxPHP

Note
  • Версионированным URL статики нужен симлинк. Magento формирует URL ресурсов вида /static/version<timestamp>/frontend/…, тогда как сами файлы лежат в pub/static/frontend/…. nginx убирает сегмент version<N>/ с помощью правила rewrite; в режиме framework-маршрутизации OxPHP такого rewrite нет, поэтому каждый версионированный ресурс отдавал бы 404, а витрина отображалась бы без стилей. Решение — самоссылающийся симлинк, который заставляет версионированный путь разрешаться в реальные файлы:

    bash
    ln -sfn . "pub/static/version$(cat pub/static/deployed_version.txt)"

    Поскольку симлинк остаётся внутри DOCUMENT_ROOT (pub/), запись в SYMLINK_ALLOW_PATHS не требуется.

  • Запускайте production-режим. Пул воркеров OxPHP многопоточный (PHP ZTS). В режиме разработчика Magento генерирует DI-классы и статические ресурсы на лету (через pub/static.php, который framework-режим не маршрутизирует), что создаёт риск гонок между потоками воркеров. deploy:mode:set production заранее компилирует DI и развёртывает статический контент, поэтому воркеры никогда не генерируют код во время обработки запроса.

  • MySQL: --log_bin_trust_function_creators=1. Во время установки Magento создаёт триггеры и хранимые функции; при включённом бинарном логировании (по умолчанию в MySQL 8.0) пользователь magento без привилегии SUPER иначе получает ошибку 1419.

  • composer install выполняется в контейнере с PHP 8.4. Штатный образ composer:2 — это PHP 8.5, который Magento отклоняет; запускайте его вместо этого через собранный образ app.

Проверка

bash
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8093/ # 200 storefront curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8093/admin # 200 admin login curl -s http://localhost:8093/ | grep -oE '/static/version[0-9]+/[^"]+\.css' | head -1 | \ xargs -I{} curl -s -o /dev/null -w "%{http_code}\n" "http://localhost:8093{}" # 200 curl -s -o /dev/null -w "%{http_code}\n" http://localhost:9094/health # 200

Смотрите также