FrankenPHP is a modern application server for PHP built on top of the Caddy web server

Overview

FrankenPHP: Modern App Server for PHP

FrankenPHP

FrankenPHP is a modern application server for PHP built on top of the Caddy web server.

FrankenPHP gives superpowers to your PHP apps thanks to its stunning features: Early Hints, worker mode, real-time capabilities, automatic HTTPS, HTTP/2 and HTTP/3 support...

FrankenPHP works with any PHP app and makes your Symfony projects faster than ever thanks to provided integration with the worker mode (Laravel Octane support coming).

FrankenPHP can also be used as a standalone Go library to embed PHP in any app using net/http.

Learn more on frankenphp.dev in this slide deck:

Slides

Getting Started

☢️ FrankenPHP is very experimental, don't use it in production yet, file bugs and write patches! ☢️

docker run -v $PWD:/app/public \
    -p 80:80 -p 443:443 \
    dunglas/frankenphp

Go to https://localhost, and enjoy!

Note: do not attempt to use https://127.0.0.1. Use localhost and accept the self-signed certificate. Caddy has an automatic TLS handling that auto-trusts some local-based hostnames like localhost, but it does not apply to IP addresses. More details on Caddy's "automatic https" docs.

Docs

Comments
  • (worker): unexpected termination

    (worker): unexpected termination

    Hi Dunglas 👋🏻

    First, thanks for this new SAPI, amazing to see how PHP can be improved for future applications.

    Small issue that I'm facing while using the worker mode, I followed the documentation for the Symfony application then launched it using Docker:

    docker run \
        -e FRANKENPHP_CONFIG="worker ./public/index.php" \
        -v $PWD:/app \       
        -p 80:80 -p 443:443 \
        dunglas/frankenphp
    WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
    
    # ...
    

    First, it seems that the v8 version is not automatically pulled, is there any issue using an arm64 image (I'm on M1 chip)?

    Second, when launched (it launched even with the warning message, it seems that it cannot be started correctly:

    {"level":"info","ts":1665988244.9370515,"msg":"using provided configuration","config_file":"/etc/Caddyfile","config_adapter":""}
    {"level":"warn","ts":1665988244.965832,"msg":"Caddyfile input is not formatted; run the 'caddy fmt' command to fix inconsistencies","adapter":"caddyfile","file":"/etc/Caddyfile","line":3}
    {"level":"info","ts":1665988244.9821901,"logger":"admin","msg":"admin endpoint started","address":"localhost:2019","enforce_origin":false,"origins":["//localhost:2019","//[::1]:2019","//127.0.0.1:2019"]}
    {"level":"info","ts":1665988244.9869301,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc000518540"}
    {"level":"info","ts":1665988244.9886699,"logger":"http","msg":"server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS","server_name":"srv0","https_port":443}
    {"level":"info","ts":1665988244.989175,"logger":"http","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
    {"level":"error","ts":1665988250.9599025,"msg":"unexpected termination, restarting","worker":"/app/public/index.php"}
    {"level":"error","ts":1665988250.9616716,"msg":"unexpected termination, restarting","worker":"/app/public/index.php"}
    {"level":"error","ts":1665988250.9628036,"msg":"unexpected termination, restarting","worker":"/app/public/index.php"}
    {"level":"error","ts":1665988250.9642198,"msg":"unexpected termination, restarting","worker":"/app/public/index.php"}
    {"level":"error","ts":1665988250.9654243,"msg":"unexpected termination, restarting","worker":"/app/public/index.php"}
    {"level":"error","ts":1665988250.9677563,"msg":"unexpected termination, restarting","worker":"/app/public/index.php"}
    

    I'm not sure why it tries to restart the worker (maybe it's due to the arm64 architecture?) but the application does not respond 🙁

    Thanks for the help and sorry for this issue 😄

    opened by Guikingone 21
  • flush() doesn't appear to work

    flush() doesn't appear to work

    Example code:

    <?php
    
    echo "hello";
    flush();
    sleep(2);
    echo "world";
    

    Frankenphp should send hello, then 2 seconds later send world. However, we end up with no response sent for 2 seconds, then helloworld sent all in one go.

    opened by withinboredom 13
  • Alpine image

    Alpine image

    • Alpine variant of the Docker image
    • Docker Bake definition file to build Bullseye and Alpine images for amd64 and arm64
    • Docs

    See the docs/docker.md for how to test.

    Needs some validation that Dockerfile.alpine has all the stuff correctly as package names and some operations are different in Alpine.

    Note: Some command chains are broken down to separate RUN lines as in build stages there is no point and separate lines make it faster to debug and use working layers.

    Resolves #42

    opened by back-2-95 13
  • POC: Enable extensions + staged build

    POC: Enable extensions + staged build

    The first stage builds PHP, taking into account some "best practices" from the official image and is built on the official image. It is a stand-in for the official image that is yet to exist (PHP 8.3).

    The second stage uses the first stage and copies in the golang build environment from the official golang image. It then builds frankenphp.

    The final stage combines the output from the first and second stages from the official PHP image. Once PHP 8.3 is released, this step will just be copying the output from the second stage instead of combining first & second stage.

    opened by withinboredom 13
  • Session handling not working in worker mode

    Session handling not working in worker mode

    I'm trying to use a bigger Symfony application in worker mode. If the caches are warm, it generally works as long as no session is used. If I visit actions containing e.g. flash message

    <div class="flashbags container">
        {% for type, messages in app.flashes %}
            ...
        {% endfor %}
    </div>
    

    I get this:

    <b>Fatal error</b>:  Uncaught RuntimeException: Failed to start the session. in /app/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php:186
    Stack trace:
    #0 /app/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php(352): Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage-&gt;start()
    #1 /app/vendor/symfony/http-foundation/Session/Session.php(261): Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage-&gt;getBag('flashes')
    #2 /app/vendor/symfony/http-foundation/Session/Session.php(273): Symfony\Component\HttpFoundation\Session\Session-&gt;getBag('flashes')
    #3 /app/vendor/symfony/twig-bridge/AppVariable.php(177): Symfony\Component\HttpFoundation\Session\Session-&gt;getFlashBag()
    
    question 
    opened by hhoechtl 9
  • Finish request early: frankenphp_finish_request

    Finish request early: frankenphp_finish_request

    This adds a new function: frankenphp_finish_request and an alias for it: fastcgi_finish_request, which follows in the footsteps of other SAPIs.

    closes #62

    opened by withinboredom 7
  • Cache (Twig) is not regenerated in dev mode

    Cache (Twig) is not regenerated in dev mode

    Hi, I use the FrankenPHP demo with the worker mode. If we modify a Twig template (with the dev env), docker has to be restarted, so the changes are taken in account. Is it a limitation of the worker mode?

    And even if we clear the cache manually, we still have to restart FrankenPHP so see the new changes.

    enhancement 
    opened by COil 7
  • Pontential memory leak in worker mode

    Pontential memory leak in worker mode

    When PHP is compiled with the --enable-debug flag, a potential memory leak is reported in worker mode when running the tests:

    go test -v
    
    [Fri Oct 21 08:21:09 2022]  Script:  '-'
    /Users/dunglas/workspace/php-src/Zend/zend_hash.c(279) :  Freeing 0x000000012aa5e000 (56 bytes), script=-
    Last leak repeated 3 times
    === Total 4 memory leaks detected ===
    

    I tried to track the potential leak with Valgrind but didn't find anything obvious yet.

    bug 
    opened by dunglas 5
  • Automatically Run Tests on PR and Push Docker Image

    Automatically Run Tests on PR and Push Docker Image

    This uses GitHub Actions to automatically run the tests in Docker via go test and publish successful builds to a Docker registry:

    • PR's are pushed to :pr-#, e.g., frankenphp:pr-38 (subject to actions approval by maintainer)
    • main branch is pushed to :main
    • tags are pushed to latest and if using semver, corresponding tags, e.g., tag v1.2.3 is tagged :1.2, :1.2.3, and latest

    See the Docker metadata action for more information.

    Requires several repo secrets:

    • REGISTRY_LOGIN_SERVER: The URL to push the docker image to.
    • REGISTRY_USERNAME: The username/org to login as.
    • REGISTRY_PASSWORD: The password to login with.
    • REGISTRY_REPO: The repository to push the docker image to.

    What is built

    Note that this builds amd64 and arm64 images and the first time this is built per branch takes ~2.5 hours.

    Documentation

    I've added some documentation about how this works, but I kinda just made it up. So we can change it here, you can change it after we merge it, or we can delete it in this PR to be added later.

    opened by withinboredom 5
  • Server hangs forever

    Server hangs forever

    I am using the same setup as described in #100 and the request just hangs indefinitely. Any idea what I can do?

    Also, but unrelated to this issue: is it possible to stop the server using ctrl+c? I always have to delete the container through Docker Desktop...

    opened by ricardoboss 4
  • follow on #50

    follow on #50

    Fix assertion error introduced in #76

    I was not able to reproduce on (intel) mac running the normal suite, do I need to do something special to reproduce, m1 maybe (I have one) ?

    This looks like the correct thing to do anyway.

    opened by krakjoe 4
  • feat: add support for PHP timeouts on Linux

    feat: add support for PHP timeouts on Linux

    Add support for PHP timeouts (require a patch to PHP).

    TODO:

    • [x] use a version of PHP containing the needed patch
    • [ ] support for timeouts in worker mode
    opened by dunglas 0
  • Consider increasing # of default workers?

    Consider increasing # of default workers?

    Currently, there is one worker spawned per core (if I'm understanding correctly).

    This severely limits concurrent connections as it appears only one request per worker can be handled at a time.

    Changing this to 2x dramatically affects the techempower benchmarks:

    from:

            {
              "latencyAvg": "421.56ms", 
              "latencyMax": "3.65s", 
              "latencyStdev": "766.41ms", 
              "totalRequests": 74185, 
              "startTime": 1671386842, 
              "endTime": 1671386858
            }
    

    to

            {
              "latencyAvg": "100.05ms", 
              "latencyMax": "1.01s", 
              "latencyStdev": "137.47ms", 
              "totalRequests": 112578, 
              "startTime": 1671387704, 
              "endTime": 1671387719
            }
    

    Anything beyond 2x has diminishing returns in my testing. FWIW, 2x on my hardware is 32 workers.

    opened by withinboredom 5
  • On unexpected shutdown, handoff connection to a another worker

    On unexpected shutdown, handoff connection to a another worker

    I've noticed that if a worker dies due to OOM (due to a memory leak, for example), it should be possible to send the request to another thread. I think this should only happen for GET requests. Is this a good idea?

    opened by withinboredom 0
  • Random PHP errors when in worker mode (extremely rare)

    Random PHP errors when in worker mode (extremely rare)

    I'm seeing random (but extremely rare: <0.5% of requests) fatal PHP errors in worker mode:

    • Cannot instantiate interface from
    • Cannot instantiate trait from
    • Cannot instantiate enum
    • Cannot instantiate abstract class

    There's no interface or trait specified in the error, just to be clear, those errors are the literal messages given. The error occurs on random lines/files.

    This never happens outside of worker mode and I cannot reproduce it in a smaller sample.

    The relevant error messages are coming from these lines in php-src. It smells like some memory shenanigans but it isn't clear if it is a frankenphp bug or a PHP/extension bug.

    bug 
    opened by withinboredom 1
  • Extend Container build to support multiple PHP version

    Extend Container build to support multiple PHP version

    This extends the Container build to support multiple versions of PHP in the FrankenPHP container images. This will make the build future proof on the one hand, so adding new versions of PHP will become a one-line change.

    On the other hand, this will also make it possible to add a specifig PHP version tag to the container image.

    Closes #112

    opened by mariusbuescher 3
  • Specific PHP version tagging

    Specific PHP version tagging

    It's unclear from the docker tags which PHP version I would be getting.

    I think for adoption it'd be good to be specific about this, even if you only want to be building 8.2, make an :php-8.2 tag so that when you update to 8.3 people can stick on the older version

    enhancement 
    opened by ciaranmcnulty 7
Owner
Kévin Dunglas
Founder of @coopTilleuls / Creator of @api-platform, Mercure.rocks and Vulcain.rocks / @symfony Core Team
Kévin Dunglas
Slim Framework view helper built on top of the Twig templating component

Slim Framework Twig View This is a Slim Framework view helper built on top of the Twig templating component. You can use this component to create and

Slim Framework 321 Dec 16, 2022
Simple, async SOAP webservice client, built on top of ReactPHP.

clue/reactphp-soap Simple, async SOAP web service client library, built on top of ReactPHP. Most notably, SOAP is often used for invoking Remote proce

Christian Lück 62 Jul 5, 2022
High-Performance Long-Living PHP Framework for modern enterprise application development

Documentation · Discord · Telegram · Twitter Spiral Framework is a High-Performance Long-Living Full-Stack framework and group of over sixty PSR-compa

Spiral Scout 1.4k Jan 1, 2023
Framework for building extensible server-side progressive applications for modern PHP.

Chevere ?? Subscribe to the newsletter to don't miss any update regarding Chevere. Framework for building extensible server-side progressive applicati

Chevere 65 Jan 6, 2023
PPM is a process manager, supercharger and load balancer for modern PHP applications.

PPM - PHP Process Manager PHP-PM is a process manager, supercharger and load balancer for PHP applications. It's based on ReactPHP and works best with

PPM - PHP Process Manager 6.5k Dec 27, 2022
:gem: Go! AOP PHP - modern aspect-oriented framework for the new level of software development

Go! Aspect-Oriented Framework for PHP Go! AOP is a modern aspect-oriented framework in plain PHP with rich features for the new level of software deve

Go! Aspect-Oriented Framework 1.6k Dec 29, 2022
A modern, ultra lightweight and rocket fast Content Management System

Redaxscript A modern, ultra lightweight and rocket fast Content Management System for SQLite, MSSQL, MySQL and PostgreSQL. Installation Clone the repo

redaxscript 247 Nov 12, 2022
Ergonode is modern PIM platform based on Symfony and Vue.js frameworks.

Modern Product Information Management Platform Ergonode is modern PIM platform based on Symfony and Vue.js frameworks. It has modular structure and gi

Ergonode 100 Dec 19, 2022
PIP is a tiny application framework built for people who use a LAMP stack.

PIP is a tiny application framework built for people who use a LAMP stack. PIP aims to be as simple as possible to set up and use.

Ron Marasigan 244 Dec 30, 2022
FlyCubePHP is an MVC Web Framework developed in PHP and repeating the ideology and principles of building WEB applications, embedded in Ruby on Rails.

FlyCubePHP FlyCubePHP is an MVC Web Framework developed in PHP and repeating the ideology and principles of building WEB applications, embedded in Rub

Anton 1 Dec 21, 2021
Rori-PHP is custom non production web application framework inspired by Laravel syntax

Rori-PHP is custom non production web application framework inspired by Laravel syntax. A web framework provides a structure and starting point for your application allowing you to focus on creating something amazing.

UnknownRori 5 Jul 28, 2022
Opulence is a PHP web application framework that simplifies the difficult parts of creating and maintaining a secure, scalable website.

Opulence Introduction Opulence is a PHP web application framework that simplifies the difficult parts of creating and maintaining a secure, scalable w

Opulence 733 Sep 8, 2022
A multithreaded application server for PHP, written in PHP.

appserver.io, a PHP application server This is the main repository for the appserver.io project. What is appserver.io appserver.io is a multithreaded

appserver.io 951 Dec 25, 2022
PHP Web Socket server

Important ⛔️ This project is no longer maintained ⛔️ We urge you to look for a replacement. Description WebSocket Server and Client library for PHP. W

Chris Tanaskoski 346 Nov 8, 2022
Newsprint is a simple web application that will fetch the front page of a newspaper and display it on an eink display

Newsprint is a simple web application that will fetch the front page of a newspaper and display it on an eink display. The specific resolutions and sizes have been setup to work with a 32" eInk place & play display from Visionect but can be modified for other screen resolutions.

Greg Raiz 199 Dec 20, 2022
Web application runner for RoadRunner

Yii RoadRunner Runner The package contains a bootstrap for running Yii3 applications using RoadRunner. Requirements PHP 7.4 or higher. Installation Th

Yii Software 18 Nov 22, 2022
The package contains a bootstrap for running Yii3 web application.

Yii Web Runner The package contains a bootstrap for running Yii3 web application. Requirements PHP 8.0 or higher. Installation The package could be in

Yii Software 4 Oct 15, 2022
🍸A Slim Web Application Template

Gracili What is Gracili? Gracili is a PHP Application Template to quickly create a new Project. Using this template can save you a lot of time. With t

Björn Pfoster 1 May 12, 2021