OxPHP で Magento を動かす

Magento は本書の中で最も重いレシピです。検索エンジン(OpenSearch)、長い拡張機能リスト、そして静的コンテンツのデプロイ手順が必須となります。ドキュメントルートを pub/ として OxPHP のフレームワークルーティングモードで動作しますが、バージョン付きの静的アセット URL については、以下で説明する追加の手順が 1 つ必要になります。

構成の概要

  • OxPHP イメージ: ghcr.io/oxphp/oxphp:0.10.0-php8.4-alpine3.23(PHP 8.4)
  • ルーティングモード: フレームワーク(ENTRY_FILE=index.phpDOCUMENT_ROOT=/var/www/html/pub はデフォルトの …/public を上書きします)
  • 追加する拡張機能: bcmathgdintlpdo_mysqlsoapxslzipmbstringftppcntlsockets
  • サービス: 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 という名前は、Magento 自身の docker アセットとの衝突を避けるために付けられています。

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 \ [email protected] --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 は /static/version<timestamp>/frontend/… のようなアセット URL を出力しますが、実際のファイルは pub/static/frontend/… に存在します。nginx はリライトルールで version<N>/ セグメントを取り除きますが、OxPHP のフレームワークモードにはそのようなリライトがないため、バージョン付きのアセットはすべて 404 となり、ストアフロントはスタイルが当たらない状態でレンダリングされてしまいます。この問題の解決策は、バージョン付きのパスを実際のファイルへ解決させる自己参照型のシンボリックリンクです。

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

    シンボリックリンクは DOCUMENT_ROOTpub/)の内側に留まるため、SYMLINK_ALLOW_PATHS のエントリは不要です。

  • 本番モードで実行してください。 OxPHP のワーカープールはマルチスレッド(PHP ZTS)です。Magento の開発者モードは DI クラスと静的アセットをその場で生成しますが(pub/static.php を経由します。これはフレームワークモードではルーティングされません)、これはワーカースレッド間での競合のリスクを伴います。deploy:mode:set production は DI を事前にコンパイルし、静的コンテンツを前もってデプロイするため、ワーカーがリクエスト時にコードを生成することは一切ありません。

  • MySQL: --log_bin_trust_function_creators=1 Magento はインストール中にトリガーとストアドファンクションを作成します。バイナリログが有効な場合(MySQL 8.0 のデフォルト)、SUPER 権限を持たない magento ユーザーは、この設定がないとエラー 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

関連情報