Running Symfony without a web server on Docker using PHP-PM

Docker containers have been becoming an increasingly common deployment method in the past few years. I've deployed some Node.js app in containers, which are very simple to deploy as there's a single process that's easy to run. I found running PHP to be more complex.

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.

Conclusion

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:

Written by Jani Tarvainen on Sunday October 22, 2017

Permalink -