FrankenPHP: современный и быстрый сервер приложений для PHP
Введение
FrankenPHP — это современный приложенческий сервер для PHP, построенный поверх мощного веб-сервера Caddy. Он сочетает в себе простоту классического PHP и производительность, сравнимую с долгоживущими процессами (Node.js, Go, Java и т.д.).
Основные преимущества FrankenPHP:
- 103 Early Hints — ускорение загрузки страниц до 30–40% за счёт предварительной отправки подсказок браузеру
- Worker mode — приложение загружается в память один раз и обрабатывает тысячи запросов без повторного бутстрапа
- Встроенная поддержка real-time — через Mercure (WebSocket-альтернатива без внешних брокеров)
- Автоматический HTTPS с Let's Encrypt, HTTP/2, HTTP/3 (QUIC)
- Очень простое развёртывание — один бинарник или один Docker-образ
- Официальная интеграция с Laravel Octane и Symfony Runtime (worker-режим работает «из коробки»)
FrankenPHP подходит любому PHP-приложению, но особенно сильно ускоряет проекты на Laravel, Symfony, Yii и других фреймворках, поддерживающих worker-режим.
Установка и запуск
Официальная документация рекомендует для Windows использовать WSL2, но самый простой и надёжный способ для
разработки и продакшена — Docker.
Официальный образ: dunglas/frankenphp (или dunglas/frankenphp:static для полностью статического бинарника).
Самый быстрый запуск (проверка)
docker run -it --rm \
-v "$(pwd)":/app/public \
-p 80:80 -p 443:443 -p 443:443/udp \
dunglas/frankenphp
Откройте в браузере: https://localhost (самоподписанный сертификат — нормально для локальной разработки) Файлы из текущей директории попадут в /app/public — это корень веб-сервера.
Полезные советы
- HTTP/3 работает сразу (порт 443/udp)
- Для продакшена используйте SERVER_NAME=вашдомен.com → Caddy сам получит настоящий сертификат
- Worker-режим не совместим с некоторыми расширениями и кодом, который использует глобальное состояние (решение — maxRequests=500 для периодического рестарта worker’а)
- Метрики Prometheus и structured logs доступны из коробки
Пример: Laravel или любой PHP-проект в Docker
Создадим типичный docker-compose.yml для сайта + база данных.
services:
site:
build:
context: .
dockerfile: Dockerfile
ports:
- "80:80"
- "443:443"
- "443:443/udp" # для HTTP/3
volumes:
- ./site:/app
environment:
SERVER_NAME: localhost # или ваш домен
# APP_ENV: production # раскомментировать в проде
# Для worker-режима (Laravel Octane / Symfony)
# CC_FRANKENPHP_WORKER: /app/public/index.php # или ваш worker-скрипт
db:
image: mariadb:10.11 # или mysql:8.4, postgresql и т.д.
env_file:
- .env.db # или прямо здесь
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: app
MYSQL_USER: app
MYSQL_PASSWORD: secret
volumes:
- db-data:/var/lib/mysql
restart: unless-stopped
Для сервера напишем Dockerfile
FROM dunglas/frankenphp:1-php8.3
# или :1-php8.4, :static и т.д.
# Увеличиваем лимиты под реальные проекты
ENV PHP_MEMORY_LIMIT=2048M
ENV PHP_MAX_EXECUTION_TIME=120
ENV SERVER_NAME=localhost
# Устанавливаем нужные расширения одной командой
RUN install-php-extensions \
pdo_mysql \
pdo_pgsql \
gd \
intl \
zip \
opcache \
redis \
imagick \
xdebug # только для dev-окружения
# Копируем проект
COPY --chown=www-data:www-data ./site /app
Пример приведен для laravel, при развертывание других приложений, важно учитывать что FrankenPHP использует по умолчанию точку входа по пути /app/public/index.php
Как включить worker-режим (самое важное ускорение)
Laravel
composer require laravel/octane
php artisan octane:install --server=frankenphp
Запуск:
frankenphp php-cli artisan octane:frankenphp --workers=auto
или добавить в docker-compose.yaml
command: frankenphp php-cli artisan octane:frankenphp --workers=auto