Magento sur OxPHP

Magento est la recette la plus lourde de cette section. Il impose un moteur de recherche (OpenSearch), une longue liste d'extensions et une étape de déploiement du contenu statique. Il s'exécute dans le mode de routage framework d'OxPHP avec pub/ comme racine du document, mais ses URL de fichiers statiques versionnées nécessitent une étape supplémentaire, décrite ci-dessous.

La stack en un coup d'œil

  • Image OxPHP : ghcr.io/oxphp/oxphp:0.10.0-php8.4-alpine3.23 (PHP 8.4)
  • Mode de routage : Framework (ENTRY_FILE=index.php ; DOCUMENT_ROOT=/var/www/html/pub remplace la valeur par défaut …/public)
  • Extensions ajoutées : bcmath, gd, intl, pdo_mysql, soap, xsl, zip, mbstring, ftp, pcntl, sockets
  • Services : OxPHP + MySQL 8.0 + OpenSearch 2.x
  • URL : http://localhost:8093 · admin /admin · interne http://localhost:9094/health
Version de PHP

Magento 2.4.8 déclare "php": "~8.2 || ~8.3 || ~8.4" et rejette PHP 8.5, il faut donc épingler l'image PHP 8.4. ext-sockets est une dépendance transitive (php-amqplib) et nécessite linux-headers pour compiler.

Organisation du projet

Magento Open Source depuis le canal de distribution officiel nécessite des clés d'authentification Adobe Marketplace. Pour l'installer sans clés, clonez le dépôt open source (ses modules sont fournis dans l'arborescence via replace, donc composer install ne récupère que les dépendances 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 et fichier compose

src/Dockerfile.oxphp est nommé ainsi pour éviter d'entrer en conflit avec les propres assets docker de 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"]

Installation et premier démarrage

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

Notes OxPHP

Note
  • Les URL statiques versionnées nécessitent un lien symbolique. Magento émet des URL d'assets comme /static/version<timestamp>/frontend/…, alors que les fichiers se trouvent dans pub/static/frontend/…. nginx supprime le segment version<N>/ grâce à une règle de réécriture ; le mode framework d'OxPHP n'a pas de réécriture de ce type, donc chaque asset versionné renverrait 404 et la vitrine s'afficherait sans styles. La solution est un lien symbolique auto-référentiel qui fait pointer le chemin versionné vers les fichiers réels :

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

    Comme le lien symbolique reste à l'intérieur de DOCUMENT_ROOT (pub/), aucune entrée SYMLINK_ALLOW_PATHS n'est requise.

  • Exécutez le mode production. Le pool de workers d'OxPHP est multithread (PHP ZTS). Le mode développeur de Magento génère les classes DI et les fichiers statiques à la volée (via pub/static.php, que le mode framework ne route pas), ce qui risque de provoquer des conditions de concurrence entre les threads de workers. deploy:mode:set production précompile la DI et déploie le contenu statique en amont, de sorte que les workers ne génèrent jamais de code au moment de la requête.

  • MySQL : --log_bin_trust_function_creators=1. Magento crée des triggers et des fonctions stockées pendant l'installation ; avec la journalisation binaire activée (valeur par défaut de MySQL 8.0), l'utilisateur magento non-SUPER déclenche sinon l'erreur 1419.

  • composer install s'exécute dans le conteneur PHP 8.4. L'image composer:2 standard est en PHP 8.5, que Magento rejette ; exécutez-la plutôt via l'image app construite.

Vérification

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

Voir aussi