Magento на OxPHP

Magento — найважчий рецепт у цьому розділі. Він вимагає пошукового рушія (OpenSearch), довгого списку розширень і окремого кроку розгортання статичного контенту. Magento працює у фреймворковому режимі маршрутизації OxPHP з pub/ як кореневим каталогом документів, але його версіоновані URL статичних ресурсів потребують одного додаткового кроку, описаного нижче.

Стек коротко

  • Образ OxPHP: ghcr.io/oxphp/oxphp:0.13.0-php8.4-alpine3.23 (PHP 8.4)
  • Режим маршрутизації: фреймворковий (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.13.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; у фреймворковому режимі OxPHP такого переписування немає, тож кожен версіонований ресурс повертав би 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, до якого фреймворковий режим не маршрутизує), що загрожує перегонами між потоками воркерів. 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

Промпти для вашого агента

Ці промпти розраховані на агента з підключеним MCP-сервером документації OxPHP — потрібні сторінки він прочитає сам.

prompt
Запусти мій магазин на Magento 2 локально на OxPHP. Прочитай сторінку `examples/ecommerce/magento` через MCP-сервер документації OxPHP. Напиши Dockerfile і файл Compose для цього репозиторію з MySQL та OpenSearch і дай мені послідовність встановлення по порядку, завершивши символьним посиланням для статичного контенту, якого потребує моя розгорнута версія.
prompt
Моя вітрина Magento на OxPHP відображається без стилів, а її URL `/static/version…` повертають 404. Прочитай сторінку `examples/ecommerce/magento` через MCP-сервер документації OxPHP. Перевір, що насправді містить мій `pub/static/` і в якому режимі працює це встановлення, а потім дай мені команду створення символьного посилання для моєї розгорнутої версії та перемикання режиму, якщо я досі в режимі розробника.

Див. також