Skip to main content

FrankenPHP

What is FrankenPHP?

FrankenPHP is a modern PHP application server built on Caddy, an alternative to the classic Nginx + PHP-FPM split. It serves your app directly (no separate web server container needed) with automatic HTTPS, HTTP/3, and a worker mode, and is the recommended runtime for Laravel Octane.

Start FrankenPHP

./laradock start frankenphp

FrankenPHP is self-contained: it doesn't declare a dependency on php-fpm or Nginx, it serves your app directly.

Stop FrankenPHP

Stopping just pauses the container, your app code on disk is untouched:

./laradock stop frankenphp

To delete the container entirely (your app code and the image are untouched):

./laradock remove frankenphp

Restart FrankenPHP

Useful after changing .env values like the ports below:

./laradock restart frankenphp

Configuration

All settings live in frankenphp/defaults.env and can be overridden by adding the same line to your own .env:

VariableDefaultWhat it does
FRANKENPHP_VERSION1-php8FrankenPHP image tag (build arg).
FRANKENPHP_HTTP_PORT8000Host-side port mapped to container port 80.
FRANKENPHP_HTTPS_PORT8443Host-side port mapped to container port 443.

Your app is mounted at /app inside the container (Laravel docroot /app/public), via ${APP_CODE_PATH_HOST}:/app.

Access your app

https://localhost:8443

HTTP on FRANKENPHP_HTTP_PORT (8000 by default) auto-redirects to HTTPS.

Add PHP extensions

Edit frankenphp/Dockerfile and add to its install-php-extensions call, then rebuild:

./laradock rebuild frankenphp

Then start it again with the rebuilt image:

./laradock start frankenphp

View logs

./laradock logs frankenphp

Caddy's access/error log lines and any PHP errors your app writes to stderr both show up here, useful for diagnosing a blank page or a certificate problem without opening a shell.

Open a shell inside the container

./laradock enter frankenphp

Since FrankenPHP is your app's PHP runtime (there's no separate php-fpm container in this stack), this is also where you'd run one-off php or php artisan commands if you want them to execute under the exact same PHP/extension set that serves requests, instead of the workspace container.

Use with Laravel Octane worker mode

For Octane's worker mode (keeping your app booted in memory between requests instead of bootstrapping per request), follow the Octane + FrankenPHP docs. The container already serves your mounted app; worker mode is configured on the Laravel side.

Common issues

  • Browser doesn't trust the HTTPS certificate. FrankenPHP, like Caddy, issues a locally trusted certificate automatically for development; trust it locally or configure a real domain for production use.
  • HTTP/3 doesn't seem to work. HTTP/3 runs over QUIC, which needs a UDP port published, but frankenphp/compose.yml only maps FRANKENPHP_HTTPS_PORT as TCP. Browsers still work fine over HTTP/1.1 or HTTP/2, but to actually get HTTP/3 locally you'd need to add a matching "${FRANKENPHP_HTTPS_PORT}:443/udp" line to the ports: list yourself.
  • Extension changes don't apply. PHP extensions are installed at build time via the Dockerfile, so after editing it you need ./laradock rebuild frankenphp, not just a restart.
  • Port already in use on your host. Another service is already bound to 8000/8443. Change FRANKENPHP_HTTP_PORT/FRANKENPHP_HTTPS_PORT and restart with ./laradock restart frankenphp.
  • App not found / blank page. Confirm your Laravel docroot is public/ under the mounted app folder, FrankenPHP expects /app/public inside the container.

Looking for the classic Nginx + PHP-FPM setup instead? See Nginx. Want another Octane-compatible runtime? See RoadRunner. New to Laradock? Start with Getting Started.