Yii3 on OxPHP
Yii3 is the leanest recipe here. The yiisoft/app template has a public/index.php front controller, needs no database, and, because most string handling is polyfilled, needs essentially no extra PHP extensions. It maps onto OxPHP's framework routing mode and runs as a single service.
Stack at a glance
- OxPHP image:
ghcr.io/oxphp/oxphp:0.13.0(PHP 8.5) - Routing mode: Framework (
ENTRY_FILE=index.php;DOCUMENT_ROOTleft at the default/var/www/html/public) - Extensions added:
mbstring(native, for speed; the runtime otherwise polyfills it) - Services: OxPHP only
- URL:
http://localhost:8094· internalhttp://localhost:9095/health
yiisoft/app declares "php": "8.2 - 8.5", so the default PHP 8.5 image fits.
Project layout
mkdir -p yii3-oxphp/src
docker run --rm -v "$PWD/yii3-oxphp/src":/app -w /app \
composer:2 create-project yiisoft/app . --prefer-dist
cp yii3-oxphp/src/.env.example yii3-oxphp/src/.envDockerfile and Compose
ARG OXPHP_VERSION=0.13.0
ARG PHP_VERSION=8.5
ARG ALPINE_VERSION=3.23
# ── PHP base: native mbstring ─────────────────────────────────
FROM php:${PHP_VERSION}-zts-alpine${ALPINE_VERSION} AS php-base
RUN apk add --no-cache oniguruma \
&& apk add --no-cache --virtual .build-deps oniguruma-dev \
&& docker-php-ext-install -j"$(nproc)" 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"]services:
app:
build:
context: ./src
target: dev
image: yii3-oxphp/app:dev
container_name: yii3-oxphp
ports:
- "8094:80"
- "9095:9090"
volumes:
- ./src:/var/www/html
environment:
# LISTEN_ADDR (0.0.0.0:80) and DOCUMENT_ROOT (/var/www/html/public) are
# the OxPHP defaults, so both are omitted.
ENTRY_FILE: index.php # framework mode
INTERNAL_ADDR: 0.0.0.0:9090
ACCESS_LOG: all
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://0.0.0.0:9090/health"]
interval: 10s
timeout: 3s
retries: 5
start_period: 5sThe yiisoft/app template ships its own whitelist-style .dockerignore; keep it. With a bind-mounted src/, the COPY is only a fallback.
Install and first run
docker compose up -d --build
docker compose exec app php yii # the Yii consoleOxPHP notes
- With no database and no extra services, this is the smallest possible OxPHP deployment: one image and one process.
yiisoft/assetspublishes static files intopublic/assets/<hash>/. They are real files on disk, and framework mode serves them directly. No URL-rewrite gymnastics are needed (unlike some asset pipelines that embed a version segment in the URL).
Verify
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8094/ # 200
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8094/nonexistent # 404 (Yii router)
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:9095/health # 200Prompts for your agent
These prompts assume an agent with the OxPHP documentation MCP server connected. The agent reads the pages it needs itself.
Run my Yii3 application on OxPHP locally. Read the `examples/framework/yii3` page through the OxPHP documentation MCP server.
Write the Dockerfile and the Compose file for this repository — the recipe is a single service with no database, so add the services my `config/` actually wires up — and give me the first-run commands.My Yii3 app runs on OxPHP but its published assets come back 404. Read the `examples/framework/yii3` page through the OxPHP documentation MCP server.
Check my asset bundles and the template's whitelist `.dockerignore` against the document root my Compose file sets, and tell me which one is losing the files.See also
- Routing · Docker Guide
- Laravel and Symfony, the other framework-mode recipes