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/pubremplace 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· internehttp://localhost:9094/health
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) :
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-distDockerfile et fichier compose
src/Dockerfile.oxphp est nommé ainsi pour éviter d'entrer en conflit avec les propres assets docker de Magento.
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"]services:
app:
build:
context: ./src
dockerfile: Dockerfile.oxphp
target: dev
image: magento-oxphp/app:dev
container_name: magento-oxphp
ports:
- "8093:80"
- "9094:9090"
volumes:
- ./src:/var/www/html
environment:
# LISTEN_ADDR defaults to 0.0.0.0:80, so it is omitted.
DOCUMENT_ROOT: /var/www/html/pub # overrides the default /var/www/html/public
ENTRY_FILE: index.php # framework mode
INTERNAL_ADDR: 0.0.0.0:9090
ACCESS_LOG: all
depends_on:
db:
condition: service_healthy
opensearch:
condition: service_healthy
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://0.0.0.0:9090/health"]
interval: 10s
timeout: 3s
retries: 5
start_period: 5s
db:
image: mysql:8.0
container_name: magento-oxphp-db
ports:
- "3310:3306"
command:
- --max_allowed_packet=64M
- --innodb-buffer-pool-size=1G
- --log_bin_trust_function_creators=1 # Magento creates triggers/functions
environment:
MYSQL_DATABASE: magento
MYSQL_USER: magento
MYSQL_PASSWORD: magento
MYSQL_ROOT_PASSWORD: root
volumes:
- db_data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-uroot", "-proot"]
interval: 5s
timeout: 5s
retries: 30
start_period: 20s
restart: unless-stopped
opensearch:
image: opensearchproject/opensearch:2.19.1
container_name: magento-oxphp-opensearch
environment:
- discovery.type=single-node
- DISABLE_SECURITY_PLUGIN=true
- DISABLE_INSTALL_DEMO_CONFIG=true
- bootstrap.memory_lock=true
- "OPENSEARCH_JAVA_OPTS=-Xms1g -Xmx1g"
ulimits:
memlock: { soft: -1, hard: -1 }
nofile: { soft: 65536, hard: 65536 }
ports:
- "9201:9200"
volumes:
- opensearch_data:/usr/share/opensearch/data
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:9200/_cluster/health || exit 1"]
interval: 10s
timeout: 5s
retries: 30
start_period: 20s
restart: unless-stopped
volumes:
db_data:
opensearch_data:Installation et premier démarrage
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 appNotes OxPHP
-
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 danspub/static/frontend/…. nginx supprime le segmentversion<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é renverrait404et 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 :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éeSYMLINK_ALLOW_PATHSn'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 productionpré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'utilisateurmagentonon-SUPERdéclenche sinon l'erreur 1419. -
composer installs'exécute dans le conteneur PHP 8.4. L'imagecomposer:2standard est en PHP 8.5, que Magento rejette ; exécutez-la plutôt via l'imageappconstruite.
Vérification
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 # 200Voir aussi
- Routage · Guide Docker · Référence de configuration
- OpenCart — l'autre recette e-commerce