Running Symfony without a web server on Docker using PHP-PM
UPDATE: Since PHP-PM 1.0 there are now official Docker images available for PHP-PM: PHP-PM 1.0 launches with official Docker images
Traditionally you ran PHP via Apache as an integrated module, which is still a valid method. But configuring Apache nowadays seems quite foreign to me. Probably most PHP projects nowadays default to setting up Nginx and PHP-FPM for PHP projects.
When running Nginx and PHP-FPM you are forced to run a pair of of containers, one for PHP-FPM and one for PHP-NPM. This setup works fine and I used it for the PHP 7.2 benchmarks with Symfony Flex as a learning experience. Since that I have also deployed a simple application based on this and it works and runs reliably.
But I would rather just run a single process to run the application. This is how Go, Node.js and even .NET Core apps are deployed. Can PHP do without a middle man?
Running Symfony with PHP-PM in a container
PHP has had the built in web server since PHP 5.2(?), and I nowadays run it for most development work I do in my local environments. But this is not recommended for production use, so it's not ideal for deployments.
Some years ago there were some efforts to serve PHP applications using a long running PHP process. Since that time options have matured, including PHP-PM that is now relatively straightforward to setup. This approach can yield high performance, but remains a niche method.
Since 2015 I've gotten to know basics of running containers and thought I would attempt to run PHP-PM in a simple container setup as an exercise. The end result is a the demo Symfony Standard Edition application setup to run PHP-PM by default.
The code is available on Github (php-pm-docker-example), but the most interesting part is probably the Dockerfile that has enough comments to explain what is going on. The end result is a container that runs a long running process manager written in PHP.
The process manages 8 worker processes, and the configuration is managed via a configuration file, ppm.json. More information on setting up and configuring in the PHP-PM documentation.
I did not do extensive testing or benchmarking on this, but just thought that I would see how this could work. It could be a valid way of running an API written in PHP with minimal bootstrapping overhead once things mature forward. This approach requires the use of PHP code that uses a HTTP request abstraction, so not every old app is a valid candidate.
It's also worth noting that the PHP-PM team is working on a rewrite based on Aerys, which could be even more robust going forward. Aerys is a stand alone HTTP/2 server written in PHP that seems quite solid and I'll try to take a closer look at it at some point as well.
At the end of the day I did manage to get to run a complete PHP framework without an external dependency on a separate HTTP server with a configuration that is easy to repeat. Whether I will ever run this in production is another question, and there is also Nginx Unit that may be an easy-to-setup PHP app server in the future.
Learn more about running PHP with alternative methods:
- PHP-PM Docker with Symfony example
- Aerys - A non-blocking HTTP application, WebSocket and file server
- PHP-PM grows up to be a credible option for high performance PHP
- Symfony Benchmarks: PHP-FPM vs. PHP-PM (on PHP 7 and HHVM)
- Running Symfony Applications with PHP-PM or PHPFastCGI