Welcome to a series of articles about ways to run PHP scripts. I will show you other ways to run your scripts. You do not always need the usual Apache/Nginx + PHP-FPM setup. In this first part, we look at the easiest method. This is the server built into PHP.
Assumptions
Before I start, here are some rules. Every method in this short series must follow these rules:
- The method must run the Slim 4 framework,
- The method must work on PHP 7.3 or newer
- We test everything on Alpine Linux, so the solution must work there
- We can compile extra PHP modules if we need them
Now we know the rules, so we can start. I talked about this method before, in my post about hello world. If you have not read it yet, go read it first. In this post, I will show you the good and bad points of this method. The main good point of the PHP server is simple: it is already part of PHP. You do not need to install any extra software or extension. If you have PHP, you already have a simple web server. This server can run any script. It can run hello world, WordPress, or a Symfony project. In our example, we use hello world built with the Slim 4 framework. You can see the code below:
<?php
declare(strict_types=1);
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
require __DIR__ . '/vendor/autoload.php';
$app = AppFactory::create();
$app->get(
'/',
function (Request $request, Response $response): Response {
$response->getBody()->write("Hello world!");
return $response;
}
);
$app->run();
Advantages
To run the script above, go to the folder with the script. Then run this command:
php -S localhost:8080
We can also choose a different document root if we need one:
php -S localhost:8080 -t public
The PHP server can also send normal files. This means it can serve CSS, JS, or images too. We do not need Apache or Nginx for this.
We only need one command to start it. So we can use it to build a simple Docker container. We do not need any supervisor tools. This kind of image is very small, just a few megabytes. You can see an example Dockerfile below:
FROM alpine
COPY www /var/www
RUN apk update \
&& apk add php composer \
&& cd /var/www \
&& composer install -o --no-dev
ENTRYPOINT php -S 0.0.0.0:80 -t /var/www
Disadvantages
This solution also has some problems. The biggest problem is this: the script runs on one thread only. This means the server cannot handle a new request until it finishes the last one. For hello world, this may not matter much. But for a script that, for example, asks a database for data, this can slow things down a lot. It can even make the service stop working for a short time, even with normal traffic.
The second problem is this: the built-in server does not support HTTPS. The only fix is to put a proxy server in front of it, like Nginx or Traefik. But that is a topic for another post.
Summary
The PHP built-in web server works best for prototypes. You can also use it to run tests. You can build a simple Docker image with a working example in just a few lines of a Dockerfile. You do not need to set up supervisors, nginx, or php-fpm. But it has no HTTPS support, and it only uses one thread. So I can say clearly: this solution is not good for production.
You can find the examples from this article on GitHub, here: https://github.com/crazy-goat/php-runtime-env/tree/master/php-server
You can download the example Docker image with this command:
sudo docker pull crazygoat/php-runtime-env:php-server
Then start it with this command:
sudo docker run -p 8080:80 --rm --name php-server crazygoat/php-runtime-env:php-server
After the container starts, you can open our hello world script here: http://localhost:8080/.