Drupal sur OxPHP
Drupal 11 utilise web/index.php comme contrôleur frontal avec des URL propres — tout chemin qui ne correspond pas à un fichier est réécrit vers index.php, ce qui correspond exactement au mode de routage framework d'OxPHP. Les CSS/JS agrégés arrivent dans web/sites/default/files/ et sont servis depuis le disque comme n'importe quel autre fichier statique.
Aperçu de la stack
- Image OxPHP :
ghcr.io/oxphp/oxphp:0.13.0-php8.4-alpine3.23(PHP 8.4) - Mode de routage : Framework (
ENTRY_FILE=index.php;DOCUMENT_ROOT=/var/www/html/webremplace la valeur par défaut…/public) - Extensions ajoutées :
gd,pdo_mysql,zip,mbstring - Services : OxPHP + MySQL
- URL :
http://localhost:8097· internehttp://localhost:9098/health
Drupal 11 exige PHP 8.3+ et prend officiellement en charge la 8.4. Sa pile de composants Symfony est antérieure à PHP 8.5, cette recette épingle donc l'image OxPHP PHP 8.4. Drupal utilise PDO (pdo_mysql), pas mysqli.
Structure du projet
mkdir -p drupal-oxphp/src
docker run --rm -e COMPOSER_ALLOW_SUPERUSER=1 \
-v "$PWD/drupal-oxphp/src":/app -w /app \
composer:2 create-project drupal/recommended-project . \
--ignore-platform-reqs --no-interaction --prefer-dist
docker run --rm -e COMPOSER_ALLOW_SUPERUSER=1 \
-v "$PWD/drupal-oxphp/src":/app -w /app \
composer:2 require drush/drush --ignore-platform-reqs --no-interaction--ignore-platform-reqs est nécessaire parce que l'image composer:2 standard n'a pas gd ; l'extension n'est requise qu'à l'exécution, où l'image OxPHP la fournit.
Dockerfile et Compose
ARG OXPHP_VERSION=0.13.0
ARG PHP_VERSION=8.4
ARG ALPINE_VERSION=3.23
# ── PHP base: Drupal runtime extensions ───────────────────────
FROM php:${PHP_VERSION}-zts-alpine${ALPINE_VERSION} AS php-base
RUN apk add --no-cache \
libpng libjpeg-turbo freetype oniguruma libzip \
&& apk add --no-cache --virtual .build-deps \
libpng-dev libjpeg-turbo-dev freetype-dev oniguruma-dev libzip-dev \
&& docker-php-ext-configure gd --with-jpeg --with-freetype \
&& docker-php-ext-install -j"$(nproc)" gd pdo_mysql zip mbstring \
&& 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 + drush ────────────
FROM php-base AS dev
RUN apk add --no-cache libgcc git
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=256M"; echo "upload_max_filesize=64M"; \
echo "post_max_size=64M"; echo "max_execution_time=300"; \
} > /usr/local/etc/php/conf.d/drupal.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/web && 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
target: dev
image: drupal-oxphp/app:dev
container_name: drupal-oxphp
ports:
- "8097:80"
- "9098: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/web # 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
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: drupal-oxphp-db
ports:
- "3312:3306"
command:
- --max_allowed_packet=64M
environment:
MYSQL_DATABASE: drupal
MYSQL_USER: drupal
MYSQL_PASSWORD: drupal
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: 15s
restart: unless-stopped
volumes:
db_data:Installation et premier lancement
drush est l'installateur non interactif le plus propre :
docker compose up -d --build
docker compose exec app vendor/bin/drush site:install standard \
--db-url=mysql://drupal:drupal@db:3306/drupal \
--account-name=admin --account-pass=admin123 \
--site-name="Drupal OxPHP" -yNotes OxPHP
- Les URL propres, c'est le mode framework. Le
RewriteCond !-f+RewriteRule ^ index.phpde Drupal fait précisément ce que fait le mode framework — servir les fichiers existants et rediriger tout le reste versweb/index.php. - Les assets agrégés sont servis depuis le disque. Drupal écrit les CSS/JS combinés dans
web/sites/default/files/csset…/js; OxPHP les sert comme des fichiers statiques. - La première requête est lente, puis rapide. La première requête à froid préchauffe la compilation Twig, l'agrégation des assets et les caches (≈15 s). Les requêtes suivantes se comptent en millisecondes à un seul chiffre. C'est le préchauffage de Drupal, pas une surcharge d'OxPHP.
Vérification
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8097/ # 200
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8097/user/login # 200
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:9098/health # 200Prompts pour votre agent
Ces prompts supposent un agent connecté au serveur MCP de la documentation OxPHP — il lira lui-même les pages dont il a besoin.
Fais tourner mon site Drupal sur OxPHP en local. Lis la page `examples/cms/drupal` via le serveur MCP de la documentation OxPHP.
Écris le Dockerfile et le fichier Compose pour ce dépôt, en épinglant la version de PHP que mes modules contrib autorisent réellement, et donne-moi la séquence drush qui l'installe contre une base de données neuve.Mon site Drupal sur OxPHP s'affiche sans styles, ou renvoie carrément 404. Lis la page `examples/cms/drupal` via le serveur MCP de la documentation OxPHP.
Compare le `DOCUMENT_ROOT` de mon fichier Compose à la racine web que mon `composer.json` met en place et à l'endroit où mes CSS et JS agrégés sont écrits, et dis-moi lequel ne colle pas.Voir aussi
- Routage · Guide Docker
- Craft CMS et October CMS — les autres recettes CMS en mode framework