Symfony on OxPHP

Symfony's public/index.php front controller drops straight into OxPHP's framework routing mode. The symfony/skeleton needs no database, so this is a single-service deployment. Add Doctrine and a db service later when you wire up persistence.

Stack at a glance

  • OxPHP image: ghcr.io/oxphp/oxphp:0.13.0 (PHP 8.5)
  • Routing mode: Framework (ENTRY_FILE=index.php; DOCUMENT_ROOT left at the default /var/www/html/public)
  • Extensions added: intl, mbstring (Symfony's recommended baseline; the runtime strictly needs only core extensions)
  • Services: OxPHP only
  • URL: http://localhost:8096 · internal http://localhost:9097/health
PHP version

Symfony 8 declares "php": ">=8.4", which the default PHP 8.5 image satisfies. Confirm a dependency does not cap the upper bound with composer check-platform-reqs --no-dev.

Project layout

bash
mkdir -p symfony-oxphp/src docker run --rm -e COMPOSER_ALLOW_SUPERUSER=1 \ -v "$PWD/symfony-oxphp/src":/app -w /app \ composer:2 create-project symfony/skeleton . --prefer-dist # optional, for a rendered page: docker run --rm -e COMPOSER_ALLOW_SUPERUSER=1 \ -v "$PWD/symfony-oxphp/src":/app -w /app \ composer:2 require twig symfony/asset

Dockerfile and compose file

src/Dockerfile
ARG OXPHP_VERSION=0.13.0 ARG PHP_VERSION=8.5 ARG ALPINE_VERSION=3.23 # ── PHP base: intl + mbstring ───────────────────────────────── FROM php:${PHP_VERSION}-zts-alpine${ALPINE_VERSION} AS php-base RUN apk add --no-cache icu-libs oniguruma \ && apk add --no-cache --virtual .build-deps icu-dev oniguruma-dev \ && docker-php-ext-install -j"$(nproc)" intl mbstring \ && apk del .build-deps # ── Composer ────────────────────────────────────────────────── FROM composer:2 AS composer # ── OxPHP artifacts (PHP 8.5 default image) ─────────────────── FROM ghcr.io/oxphp/oxphp:${OXPHP_VERSION} AS oxphp # ── dev: OxPHP server + PHP CLI + Composer ──────────────────── 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 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/public && chown -R www-data:www-data /var/www/html ENV LD_LIBRARY_PATH=/usr/local/lib WORKDIR /var/www/html COPY --chown=www-data:www-data . /var/www/html EXPOSE 80 9090 CMD ["oxphp"]

Install and first run

bash
docker compose up -d --build docker compose exec app php bin/console about

OxPHP notes

Note
  • The extension footprint is small. The Symfony skeleton's runtime needs only core extensions (ctype, iconv, xml), all present in the base image, and mbstring is otherwise polyfilled. Native intl + mbstring are added because any real Symfony app uses them and the native versions are faster than the polyfill.
  • APP_ENV comes from the container environment. Symfony reads it from the real environment over .env, so set it in Compose.
  • Framework mode serves static assets from public/. {{ asset('css/app.css') }} resolves to a real file on disk and is served directly. A request falls through to index.php only on a miss.

Verify

bash
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8096/ # 200 curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8096/no-such-route # 404 (Symfony router) curl -s -o /dev/null -w "%{http_code}\n" http://localhost:9097/health # 200

Prompts for your agent

These prompts assume an agent with the OxPHP documentation MCP server connected. The agent reads the pages it needs itself.

prompt
Run my Symfony application on OxPHP locally. Read the `examples/framework/symfony` page through the OxPHP documentation MCP server. Write the Dockerfile and the Compose file for this repository — the recipe is a single service, so add back the database, cache and messenger transports my app really uses — and install only the extensions my dependencies require.
prompt
My Symfony app runs on OxPHP but it is not picking up the configuration I expect. Read the `examples/framework/symfony` page through the OxPHP documentation MCP server. Compare the variables my Compose file exports with what my `.env` and `.env.local` set, and tell me which of these values the container environment is overriding.

See also

Found a mistake? Report it →