Factor #7: Port binding
Export services via port binding
This is probably the most difficult factor to apply to WordPress and that's because of PHP.
Web apps are sometimes executed inside a webserver container. For example, PHP apps might run as a module inside Apache HTTPD, or Java apps might run inside Tomcat.
The twelve-factor app is completely self-contained and does not rely on runtime injection of a webserver into the execution environment to create a web-facing service. The web app exports HTTP as a service by binding to a port, and listening to requests coming in on that port.
Obviously Apache with mod_php is out of the question here since it directly violates the above. But what about Nginx with PHP-FPM?
In a local development environment, the developer visits a service URL like http://localhost:5000/ to access the service exported by their app. In deployment, a routing layer handles routing requests from a public-facing hostname to the port-bound web processes.
This is typically implemented by using dependency declaration to add a webserver library to the app, such as Tornado for Python, Thin for Ruby, or Jetty for Java and other JVM-based languages. This happens entirely in user space, that is, within the app’s code. The contract with the execution environment is binding to a port to serve requests.
PHP-FPM is a FastCGI implementation and not an actual web server library. You can't just run PHP-FPM and visit the URL in your browser. You also can't directly use it in development since you'd still need Nginx in front of it. But PHP-FPM does at least bind to a socket which mean it's not relying on runtime injection.
The only PHP equivalent is the new built-in web server in 5.4. However, as it says in the link above, don't use it in production. While you could use it in development and then switch to Nginx+PHP-FPM in production, this isn't ideal and as mentioned before, still wouldn't satisfy this factor's requirements.
We might not be able to completely comply with the Port Binding factor, but let's do the best we can.
First, definitely use Nginx + PHP-FPM in production. Thankfully this is becoming a more common configuration since it offers more flexibility and much better performance than Apache + mod_php.
However, most people just use the default install configuration for PHP-FPM. That means using a global config (something like
/etc/php-fpm.conf) and running the processes as
root. It might be beneficial to have your
php-fpm.conf as part of your codebase and run PHP-FPM specifying that conf location. That way you can have a different conf for each site/codebase all self-contained.
At a minimum the user should be changed to something other than root through
listen.owner and the
- Backing Services
- Build, release, run
- Port binding
- Dev/prod parity
- Admin processes
Want to turn your WordPress site into a Twelve-factor App? Bedrock is a modern WordPress stack to help you get started with the best tools and practices.