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

docker compose up -d frankenphp

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

Stop FrankenPHP

docker compose stop 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:

docker compose build frankenphp
docker compose up -d frankenphp

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.
  • Extension changes don't apply. PHP extensions are installed at build time via the Dockerfile, so after editing it you need docker compose build 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.
  • 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.