diff --git a/CHANGELOG.md b/CHANGELOG.md index 35bda063..e1a86e95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ ### Minor changes * **2026-10-09** + * New documentation page for the fpm variant: serving HTTP (built-in Apache or another web server), constraints of PHP-FPM and migration from the apache variant + * fpm variant: the time the built-in Apache waits for PHP-FPM can be configured with `APACHE_PROXY_TIMEOUT` (300 seconds by default) + * Fix PHP-FPM not starting when the working directory belongs to root (`[pool www] user has not been defined`): its workers now run with the Apache user + * fpm variant: optional built-in Apache (`PHP_FPM_WEB_SERVER=apache`): Apache (`mpm_event`) in front of PHP-FPM in the same container. Same features as the `apache` variant (`.htaccess`, `APACHE_DOCUMENT_ROOT`, `APACHE_EXTENSION_*`), lower memory usage and much better handling of concurrent connections (see `benchmarks/fpm-apache`) + * PHP-FPM: the process manager and the access log can be configured with `PHP_FPM_PM*` and `PHP_FPM_ACCESS_LOG` environment variables + * PHP-FPM: new `php-fpm-healthcheck` command (ping endpoint), usable as a Docker healthcheck or a Kubernetes probe + * Accept the `http2` and `proxy_http2` Apache modules in `APACHE_EXTENSION_*` (HTTP/2 requires a threaded MPM such as `mpm_event`: it is not served with the `mpm_prefork` MPM required by mod_php) + * Fix switching the Apache MPM with `APACHE_EXTENSION_*` (modules are now disabled before being enabled, the MPM last) * Upgrade Supercronic from 0.1.9 to 0.2.49 (built with an up-to-date Go version) * Fix Composer and NodeJS binaries (`vendor/bin`, `node_modules/.bin` and global Composer binaries) not found by `docker exec` / `docker compose exec` when run without their path * Fix extensions that could not be loaded without another extension: the required extensions are now enabled with them (`memcached` requires `igbinary` and `msgpack`, `redis` requires `igbinary`, `mailparse` requires `mbstring` and `swoole` requires `curl`) diff --git a/Dockerfile.slim.apache b/Dockerfile.slim.apache index 24b60e1d..341b82ba 100644 --- a/Dockerfile.slim.apache +++ b/Dockerfile.slim.apache @@ -161,6 +161,7 @@ RUN composer global require bamarni/symfony-console-autocomplete && \ USER root +# Apache: built-in web server of the fpm variant (disabled by default, see PHP_FPM_WEB_SERVER) ENV APACHE_CONFDIR=/etc/apache2 ENV APACHE_ENVVARS=$APACHE_CONFDIR/envvars @@ -200,20 +201,19 @@ RUN set -eux; \ ln -sfT /dev/stdout "$APACHE_LOG_DIR/other_vhosts_access.log"; \ chown -R --no-dereference "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$APACHE_LOG_DIR" -# Apache + PHP requires preforking Apache for best results + +# Apache + mod_php requires preforking Apache (mod_php is not thread-safe) RUN a2dismod mpm_event && a2enmod mpm_prefork # PHP files should be handled by PHP, and should be preferred over any other file type COPY utils/apache-docker-php.conf /etc/apache2/conf-available/docker-php.conf -RUN a2enconf docker-php - -ENV PHP_EXTRA_BUILD_DEPS=apache2-dev -ENV PHP_EXTRA_CONFIGURE_ARGS="--with-apxs2 --disable-cgi" - # https://httpd.apache.org/docs/2.4/stopping.html#gracefulstop STOPSIGNAL SIGWINCH + +RUN a2enconf docker-php + COPY utils/apache2-foreground /usr/local/bin/ EXPOSE 80 @@ -223,9 +223,11 @@ ENV APACHE_DOCUMENT_ROOT= RUN sed -ri -e 's!/var/www/html!${ABSOLUTE_APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf && \ sed -ri -e 's!/var/www/!${ABSOLUTE_APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf + # Let's remove the default Apache php.ini file (it will be copied from TEMPLATE_PHP_INI) RUN rm /etc/php/${PHP_VERSION}/apache2/php.ini + # |-------------------------------------------------------------------------- # | Apache mod_rewrite # |-------------------------------------------------------------------------- @@ -318,6 +320,8 @@ COPY utils/generate_cron.php /usr/local/bin/generate_cron.php COPY utils/startup_commands.php /usr/local/bin/startup_commands.php COPY utils/enable_apache_mods.php /usr/local/bin/enable_apache_mods.php + + COPY utils/apache-expose-envvars.sh /usr/local/bin/apache-expose-envvars.sh COPY utils/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh @@ -333,8 +337,10 @@ ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"] RUN echo "ServerName localhost" > /etc/apache2/conf-available/servername.conf && \ a2enconf servername + CMD ["apache2-foreground"] + # |-------------------------------------------------------------------------- # | Entrypoint # |-------------------------------------------------------------------------- diff --git a/Dockerfile.slim.cli b/Dockerfile.slim.cli index 5a242b8f..7a32e37f 100644 --- a/Dockerfile.slim.cli +++ b/Dockerfile.slim.cli @@ -243,6 +243,7 @@ ENV IMAGE_VARIANT=cli COPY utils/generate_cron.php /usr/local/bin/generate_cron.php COPY utils/startup_commands.php /usr/local/bin/startup_commands.php + COPY utils/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh COPY utils/docker-entrypoint-as-root.sh /usr/local/bin/docker-entrypoint-as-root.sh diff --git a/Dockerfile.slim.fpm b/Dockerfile.slim.fpm index 3633cc2d..6784b05c 100644 --- a/Dockerfile.slim.fpm +++ b/Dockerfile.slim.fpm @@ -161,10 +161,81 @@ RUN composer global require bamarni/symfony-console-autocomplete && \ USER root +# Apache: built-in web server of the fpm variant (disabled by default, see PHP_FPM_WEB_SERVER) +ENV APACHE_CONFDIR=/etc/apache2 +ENV APACHE_ENVVARS=$APACHE_CONFDIR/envvars + +RUN set -eux; \ + apt update; \ + apt install -y --no-install-recommends apache2; \ + rm -rf /var/lib/apt/lists/*; \ + \ +# generically convert lines like +# export APACHE_RUN_USER=www-data +# into +# : ${APACHE_RUN_USER:=www-data} +# export APACHE_RUN_USER +# so that they can be overridden at runtime ("-e APACHE_RUN_USER=...") + sed -ri 's/^export ([^=]+)=(.*)$/: ${\1:=\2}\nexport \1/' "$APACHE_ENVVARS"; \ + \ +# setup directories and permissions + . "$APACHE_ENVVARS"; \ + for dir in \ + "$APACHE_LOCK_DIR" \ + "$APACHE_RUN_DIR" \ + "$APACHE_LOG_DIR" \ + ; do \ + rm -rvf "$dir"; \ + mkdir -p "$dir"; \ + chown "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$dir"; \ +# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743) + chmod 777 "$dir"; \ + done; \ + \ +# delete the "index.html" that installing Apache drops in here + rm -rvf /var/www/html/*; \ + \ +# logs should go to stdout / stderr + ln -sfT /dev/stderr "$APACHE_LOG_DIR/error.log"; \ + ln -sfT /dev/stdout "$APACHE_LOG_DIR/access.log"; \ + ln -sfT /dev/stdout "$APACHE_LOG_DIR/other_vhosts_access.log"; \ + chown -R --no-dereference "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$APACHE_LOG_DIR" + + +# Apache keeps its default threaded MPM (mpm_event) and forwards PHP files to PHP-FPM +RUN a2enmod proxy_fcgi setenvif + +# PHP files should be handled by PHP-FPM, and should be preferred over any other file type +COPY utils/apache-docker-php-fpm.conf /etc/apache2/conf-available/docker-php.conf + + +RUN a2enconf docker-php + +COPY utils/apache2-foreground /usr/local/bin/ + +EXPOSE 80 + +ENV APACHE_DOCUMENT_ROOT= + +RUN sed -ri -e 's!/var/www/html!${ABSOLUTE_APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf && \ + sed -ri -e 's!/var/www/!${ABSOLUTE_APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf + +# |-------------------------------------------------------------------------- +# | Apache mod_rewrite +# |-------------------------------------------------------------------------- +# | +# | Enables Apache mod_rewrite. +# | + +RUN a2enmod rewrite + + + +# libfcgi-bin provides cgi-fcgi, used by php-fpm-healthcheck RUN apt update \ - && apt install -y --no-install-recommends php${PHP_VERSION}-fpm \ + && apt install -y --no-install-recommends php${PHP_VERSION}-fpm libfcgi-bin \ && apt clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/* @@ -172,8 +243,25 @@ RUN apt update \ RUN rm /etc/php/${PHP_VERSION}/fpm/php.ini && \ ln -s /usr/sbin/php-fpm${PHP_VERSION} /usr/sbin/php-fpm COPY utils/fpm-docker.conf /etc/php/${PHP_VERSION}/fpm/pool.d/docker.conf +COPY utils/fpm-zz-docker-pm.conf /etc/php/${PHP_VERSION}/fpm/pool.d/zz-docker-pm.conf +COPY utils/php-fpm-healthcheck /usr/local/bin/php-fpm-healthcheck + +# PHP-FPM process manager (defaults are the ones of the Ubuntu package) +ENV PHP_FPM_PM=dynamic \ + PHP_FPM_PM_MAX_CHILDREN=5 \ + PHP_FPM_PM_START_SERVERS=2 \ + PHP_FPM_PM_MIN_SPARE_SERVERS=1 \ + PHP_FPM_PM_MAX_SPARE_SERVERS=3 \ + PHP_FPM_PM_MAX_REQUESTS=0 \ + PHP_FPM_ACCESS_LOG=/proc/self/fd/2 + COPY utils/fpm-zz-docker.conf /etc/php/${PHP_VERSION}/fpm/pool.d/zz-docker.conf +# Built-in web server: "apache" runs Apache in front of PHP-FPM (empty: PHP-FPM only) +ENV PHP_FPM_WEB_SERVER= \ + APACHE_PROXY_TIMEOUT=300 +COPY utils/apache2-fpm-foreground /usr/local/bin/ + EXPOSE 9000 STOPSIGNAL SIGQUIT @@ -260,6 +348,9 @@ ENV IMAGE_VARIANT=fpm COPY utils/generate_cron.php /usr/local/bin/generate_cron.php COPY utils/startup_commands.php /usr/local/bin/startup_commands.php +COPY utils/enable_apache_mods.php /usr/local/bin/enable_apache_mods.php + + COPY utils/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh COPY utils/docker-entrypoint-as-root.sh /usr/local/bin/docker-entrypoint-as-root.sh @@ -269,6 +360,24 @@ RUN ln -s ${PHP_VERSION} /usr/local/lib/thecodingmachine-php/extensions/current ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"] +# Let's register a servername to remove the message "apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message" +RUN echo "ServerName localhost" > /etc/apache2/conf-available/servername.conf && \ + a2enconf servername + + + +# |-------------------------------------------------------------------------- +# | Entrypoint +# |-------------------------------------------------------------------------- +# | +# | Defines Apache user. By default, we switch this to "docker" user. +# | This way, no problem to write from Apache in the current working directory. +# | Important! This should be changed back to www-data in production. +# | + +ENV APACHE_RUN_USER=docker \ + APACHE_RUN_GROUP=docker + CMD ["php-fpm"] diff --git a/README.md b/README.md index 8328d55d..a9be16a6 100644 --- a/README.md +++ b/README.md @@ -3,12 +3,30 @@ # General purpose PHP images for Docker +> **New: built-in Apache in the fpm variant (`PHP_FPM_WEB_SERVER=apache`)** +> +> The *fpm* variant can now run Apache in front of PHP-FPM, in the same container. It is a drop-in alternative to the +> *apache* variant: same Apache features (`.htaccess`, `APACHE_DOCUMENT_ROOT`, `APACHE_EXTENSION_*`), but PHP runs in +> PHP-FPM instead of `mod_php`. +> +> **Why?** Under the same load ([benchmark](benchmarks/fpm-apache)), the container serves **2 to 3 times more traffic +> with 4 times less memory** (30 vs 10 pages/s on 2 CPUs, ~90 vs ~380 MiB). `mod_php` forces Apache to dedicate a +> whole process embedding PHP to each connection, including idle keep-alive connections and static files. With +> PHP-FPM, Apache uses its threaded MPM (`mpm_event`) and only PHP requests reach the PHP workers. +> +> ```bash +> $ docker run -p 80:80 -e PHP_FPM_WEB_SERVER=apache -v "$PWD":/var/www/html thecodingmachine/php:8.4-v5-fpm +> ``` +> +> **[Read more: advantages, constraints of PHP-FPM and migration from the *apache* variant](docs/fpm.md)** +> (for instance, `php_value` directives are not supported in `.htaccess` files). The *apache* variant is still available. + This repository contains a set of developer-friendly, general purpose PHP images for Docker. - You can enable or disable the extensions using environment variables. - You can also modify the `php.ini` settings using environment variables. - 2 types available: `slim` (no extensions preloaded) or `fat` (most common PHP extensions are built-in) - - 3 variants available: `CLI`, `apache` and `fpm` + - 3 variants available: `CLI`, `apache` and `fpm` (with an optional built-in Apache) - Fat images are bundled with [Supercronic](https://github.com/aptible/supercronic) which is a Cron compatible task runner. Cron jobs can be configured using environment variables - Fat images come with [Composer](https://getcomposer.org/) and [Prestissimo](https://github.com/hirak/prestissimo) installed - All variants can be installed with or without NodeJS (if you need to build your static assets). @@ -23,84 +41,84 @@ This repository contains a set of developer-friendly, general purpose PHP images | Name | PHP version | type |variant | NodeJS version | Size |-------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------|--------|-----------------|------ -| [thecodingmachine/php:8.5-v5-apache](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.apache) | `8.5.x` | fat | apache | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-apache.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-apache) -| [thecodingmachine/php:8.5-v5-apache-node22](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.apache.node) | `8.5.x` | fat | apache | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-apache-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-apache-node22) -| [thecodingmachine/php:8.5-v5-apache-node24](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.apache.node) | `8.5.x` | fat | apache | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-apache-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-apache-node24) -| [thecodingmachine/php:8.5-v5-apache-node26](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.apache.node) | `8.5.x` | fat | apache | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-apache-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-apache-node26) -| [thecodingmachine/php:8.5-v5-fpm](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.fpm) | `8.5.x` | fat | fpm | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-fpm.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-fpm) -| [thecodingmachine/php:8.5-v5-fpm-node22](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.fpm.node) | `8.5.x` | fat | fpm | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-fpm-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-fpm-node22) -| [thecodingmachine/php:8.5-v5-fpm-node24](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.fpm.node) | `8.5.x` | fat | fpm | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-fpm-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-fpm-node24) -| [thecodingmachine/php:8.5-v5-fpm-node26](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.fpm.node) | `8.5.x` | fat | fpm | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-fpm-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-fpm-node26) -| [thecodingmachine/php:8.5-v5-cli](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.cli) | `8.5.x` | fat | cli | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-cli.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-cli) -| [thecodingmachine/php:8.5-v5-cli-node22](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.cli.node) | `8.5.x` | fat | cli | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-cli-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-cli-node22) -| [thecodingmachine/php:8.5-v5-cli-node24](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.cli.node) | `8.5.x` | fat | cli | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-cli-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-cli-node24) -| [thecodingmachine/php:8.5-v5-cli-node26](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.cli.node) | `8.5.x` | fat | cli | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-cli-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-cli-node26) -| [thecodingmachine/php:8.5-v5-slim-apache](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.slim.apache) | `8.5.x` | slim | apache | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-slim-apache.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-slim-apache) -| [thecodingmachine/php:8.5-v5-slim-fpm](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.slim.fpm) | `8.5.x` | slim | fpm | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-slim-fpm.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-slim-fpm) -| [thecodingmachine/php:8.5-v5-slim-cli](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.slim.cli) | `8.5.x` | slim | cli | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-slim-cli.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-slim-cli) -| [thecodingmachine/php:8.4-v5-apache](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.apache) | `8.4.x` | fat | apache | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-apache.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-apache) -| [thecodingmachine/php:8.4-v5-apache-node22](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.apache.node) | `8.4.x` | fat | apache | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-apache-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-apache-node22) -| [thecodingmachine/php:8.4-v5-apache-node24](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.apache.node) | `8.4.x` | fat | apache | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-apache-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-apache-node24) -| [thecodingmachine/php:8.4-v5-apache-node26](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.apache.node) | `8.4.x` | fat | apache | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-apache-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-apache-node26) -| [thecodingmachine/php:8.4-v5-fpm](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.fpm) | `8.4.x` | fat | fpm | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-fpm.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-fpm) -| [thecodingmachine/php:8.4-v5-fpm-node22](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.fpm.node) | `8.4.x` | fat | fpm | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-fpm-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-fpm-node22) -| [thecodingmachine/php:8.4-v5-fpm-node24](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.fpm.node) | `8.4.x` | fat | fpm | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-fpm-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-fpm-node24) -| [thecodingmachine/php:8.4-v5-fpm-node26](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.fpm.node) | `8.4.x` | fat | fpm | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-fpm-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-fpm-node26) -| [thecodingmachine/php:8.4-v5-cli](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.cli) | `8.4.x` | fat | cli | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-cli.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-cli) -| [thecodingmachine/php:8.4-v5-cli-node22](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.cli.node) | `8.4.x` | fat | cli | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-cli-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-cli-node22) -| [thecodingmachine/php:8.4-v5-cli-node24](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.cli.node) | `8.4.x` | fat | cli | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-cli-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-cli-node24) -| [thecodingmachine/php:8.4-v5-cli-node26](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.cli.node) | `8.4.x` | fat | cli | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-cli-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-cli-node26) -| [thecodingmachine/php:8.4-v5-slim-apache](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.slim.apache) | `8.4.x` | slim | apache | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-slim-apache.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-slim-apache) -| [thecodingmachine/php:8.4-v5-slim-fpm](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.slim.fpm) | `8.4.x` | slim | fpm | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-slim-fpm.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-slim-fpm) -| [thecodingmachine/php:8.4-v5-slim-cli](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.slim.cli) | `8.4.x` | slim | cli | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-slim-cli.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-slim-cli) -| [thecodingmachine/php:8.3-v5-apache](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.apache) | `8.3.x` | fat | apache | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-apache.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-apache) -| [thecodingmachine/php:8.3-v5-apache-node22](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.apache.node) | `8.3.x` | fat | apache | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-apache-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-apache-node22) -| [thecodingmachine/php:8.3-v5-apache-node24](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.apache.node) | `8.3.x` | fat | apache | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-apache-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-apache-node24) -| [thecodingmachine/php:8.3-v5-apache-node26](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.apache.node) | `8.3.x` | fat | apache | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-apache-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-apache-node26) -| [thecodingmachine/php:8.3-v5-fpm](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.fpm) | `8.3.x` | fat | fpm | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-fpm.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-fpm) -| [thecodingmachine/php:8.3-v5-fpm-node22](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.fpm.node) | `8.3.x` | fat | fpm | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-fpm-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-fpm-node22) -| [thecodingmachine/php:8.3-v5-fpm-node24](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.fpm.node) | `8.3.x` | fat | fpm | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-fpm-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-fpm-node24) -| [thecodingmachine/php:8.3-v5-fpm-node26](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.fpm.node) | `8.3.x` | fat | fpm | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-fpm-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-fpm-node26) -| [thecodingmachine/php:8.3-v5-cli](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.cli) | `8.3.x` | fat | cli | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-cli.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-cli) -| [thecodingmachine/php:8.3-v5-cli-node22](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.cli.node) | `8.3.x` | fat | cli | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-cli-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-cli-node22) -| [thecodingmachine/php:8.3-v5-cli-node24](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.cli.node) | `8.3.x` | fat | cli | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-cli-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-cli-node24) -| [thecodingmachine/php:8.3-v5-cli-node26](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.cli.node) | `8.3.x` | fat | cli | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-cli-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-cli-node26) -| [thecodingmachine/php:8.3-v5-slim-apache](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.slim.apache) | `8.3.x` | slim | apache | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-slim-apache.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-slim-apache) -| [thecodingmachine/php:8.3-v5-slim-fpm](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.slim.fpm) | `8.3.x` | slim | fpm | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-slim-fpm.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-slim-fpm) -| [thecodingmachine/php:8.3-v5-slim-cli](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.slim.cli) | `8.3.x` | slim | cli | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-slim-cli.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-slim-cli) -| [thecodingmachine/php:8.2-v5-apache](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.apache) | `8.2.x` | fat | apache | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-apache.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-apache) -| [thecodingmachine/php:8.2-v5-apache-node22](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.apache.node) | `8.2.x` | fat | apache | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-apache-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-apache-node22) -| [thecodingmachine/php:8.2-v5-apache-node24](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.apache.node) | `8.2.x` | fat | apache | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-apache-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-apache-node24) -| [thecodingmachine/php:8.2-v5-apache-node26](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.apache.node) | `8.2.x` | fat | apache | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-apache-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-apache-node26) -| [thecodingmachine/php:8.2-v5-fpm](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.fpm) | `8.2.x` | fat | fpm | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-fpm.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-fpm) -| [thecodingmachine/php:8.2-v5-fpm-node22](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.fpm.node) | `8.2.x` | fat | fpm | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-fpm-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-fpm-node22) -| [thecodingmachine/php:8.2-v5-fpm-node24](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.fpm.node) | `8.2.x` | fat | fpm | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-fpm-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-fpm-node24) -| [thecodingmachine/php:8.2-v5-fpm-node26](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.fpm.node) | `8.2.x` | fat | fpm | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-fpm-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-fpm-node26) -| [thecodingmachine/php:8.2-v5-cli](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.cli) | `8.2.x` | fat | cli | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-cli.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-cli) -| [thecodingmachine/php:8.2-v5-cli-node22](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.cli.node) | `8.2.x` | fat | cli | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-cli-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-cli-node22) -| [thecodingmachine/php:8.2-v5-cli-node24](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.cli.node) | `8.2.x` | fat | cli | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-cli-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-cli-node24) -| [thecodingmachine/php:8.2-v5-cli-node26](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.cli.node) | `8.2.x` | fat | cli | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-cli-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-cli-node26) -| [thecodingmachine/php:8.2-v5-slim-apache](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.slim.apache) | `8.2.x` | slim | apache | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-slim-apache.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-slim-apache) -| [thecodingmachine/php:8.2-v5-slim-fpm](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.slim.fpm) | `8.2.x` | slim | fpm | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-slim-fpm.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-slim-fpm) -| [thecodingmachine/php:8.2-v5-slim-cli](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.slim.cli) | `8.2.x` | slim | cli | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-slim-cli.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-slim-cli) -| [thecodingmachine/php:8.1-v5-apache](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.apache) | `8.1.x` | fat | apache | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-apache.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-apache) -| [thecodingmachine/php:8.1-v5-apache-node20](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.apache.node) | `8.1.x` | fat | apache | `20.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-apache-node20.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-apache-node20) -| [thecodingmachine/php:8.1-v5-apache-node22](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.apache.node) | `8.1.x` | fat | apache | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-apache-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-apache-node22) -| [thecodingmachine/php:8.1-v5-apache-node24](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.apache.node) | `8.1.x` | fat | apache | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-apache-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-apache-node24) -| [thecodingmachine/php:8.1-v5-apache-node26](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.apache.node) | `8.1.x` | fat | apache | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-apache-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-apache-node26) -| [thecodingmachine/php:8.1-v5-fpm](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.fpm) | `8.1.x` | fat | fpm | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-fpm.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-fpm) -| [thecodingmachine/php:8.1-v5-fpm-node20](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.fpm.node) | `8.1.x` | fat | fpm | `20.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-fpm-node20.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-fpm-node20) -| [thecodingmachine/php:8.1-v5-fpm-node22](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.fpm.node) | `8.1.x` | fat | fpm | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-fpm-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-fpm-node22) -| [thecodingmachine/php:8.1-v5-fpm-node24](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.fpm.node) | `8.1.x` | fat | fpm | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-fpm-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-fpm-node24) -| [thecodingmachine/php:8.1-v5-fpm-node26](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.fpm.node) | `8.1.x` | fat | fpm | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-fpm-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-fpm-node26) -| [thecodingmachine/php:8.1-v5-cli](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.cli) | `8.1.x` | fat | cli | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-cli.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-cli) -| [thecodingmachine/php:8.1-v5-cli-node20](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.cli.node) | `8.1.x` | fat | cli | `20.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-cli-node20.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-cli-node20) -| [thecodingmachine/php:8.1-v5-cli-node22](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.cli.node) | `8.1.x` | fat | cli | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-cli-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-cli-node22) -| [thecodingmachine/php:8.1-v5-cli-node24](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.cli.node) | `8.1.x` | fat | cli | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-cli-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-cli-node24) -| [thecodingmachine/php:8.1-v5-cli-node26](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.cli.node) | `8.1.x` | fat | cli | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-cli-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-cli-node26) -| [thecodingmachine/php:8.1-v5-slim-apache](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.slim.apache) | `8.1.x` | slim | apache | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-slim-apache.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-slim-apache) -| [thecodingmachine/php:8.1-v5-slim-fpm](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.slim.fpm) | `8.1.x` | slim | fpm | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-slim-fpm.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-slim-fpm) -| [thecodingmachine/php:8.1-v5-slim-cli](https://github.com/thecodingmachine/docker-images-php/blob/v5/Dockerfile.slim.cli) | `8.1.x` | slim | cli | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-slim-cli.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-slim-cli) +| [thecodingmachine/php:8.5-v5-apache](Dockerfile.apache) | `8.5.x` | fat | apache | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-apache.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-apache) +| [thecodingmachine/php:8.5-v5-apache-node22](Dockerfile.apache.node) | `8.5.x` | fat | apache | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-apache-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-apache-node22) +| [thecodingmachine/php:8.5-v5-apache-node24](Dockerfile.apache.node) | `8.5.x` | fat | apache | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-apache-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-apache-node24) +| [thecodingmachine/php:8.5-v5-apache-node26](Dockerfile.apache.node) | `8.5.x` | fat | apache | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-apache-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-apache-node26) +| [thecodingmachine/php:8.5-v5-fpm](Dockerfile.fpm) | `8.5.x` | fat | fpm | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-fpm.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-fpm) +| [thecodingmachine/php:8.5-v5-fpm-node22](Dockerfile.fpm.node) | `8.5.x` | fat | fpm | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-fpm-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-fpm-node22) +| [thecodingmachine/php:8.5-v5-fpm-node24](Dockerfile.fpm.node) | `8.5.x` | fat | fpm | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-fpm-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-fpm-node24) +| [thecodingmachine/php:8.5-v5-fpm-node26](Dockerfile.fpm.node) | `8.5.x` | fat | fpm | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-fpm-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-fpm-node26) +| [thecodingmachine/php:8.5-v5-cli](Dockerfile.cli) | `8.5.x` | fat | cli | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-cli.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-cli) +| [thecodingmachine/php:8.5-v5-cli-node22](Dockerfile.cli.node) | `8.5.x` | fat | cli | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-cli-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-cli-node22) +| [thecodingmachine/php:8.5-v5-cli-node24](Dockerfile.cli.node) | `8.5.x` | fat | cli | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-cli-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-cli-node24) +| [thecodingmachine/php:8.5-v5-cli-node26](Dockerfile.cli.node) | `8.5.x` | fat | cli | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-cli-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-cli-node26) +| [thecodingmachine/php:8.5-v5-slim-apache](Dockerfile.slim.apache) | `8.5.x` | slim | apache | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-slim-apache.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-slim-apache) +| [thecodingmachine/php:8.5-v5-slim-fpm](Dockerfile.slim.fpm) | `8.5.x` | slim | fpm | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-slim-fpm.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-slim-fpm) +| [thecodingmachine/php:8.5-v5-slim-cli](Dockerfile.slim.cli) | `8.5.x` | slim | cli | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.5-v5-slim-cli.svg)](https://microbadger.com/images/thecodingmachine/php:8.5-v5-slim-cli) +| [thecodingmachine/php:8.4-v5-apache](Dockerfile.apache) | `8.4.x` | fat | apache | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-apache.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-apache) +| [thecodingmachine/php:8.4-v5-apache-node22](Dockerfile.apache.node) | `8.4.x` | fat | apache | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-apache-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-apache-node22) +| [thecodingmachine/php:8.4-v5-apache-node24](Dockerfile.apache.node) | `8.4.x` | fat | apache | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-apache-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-apache-node24) +| [thecodingmachine/php:8.4-v5-apache-node26](Dockerfile.apache.node) | `8.4.x` | fat | apache | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-apache-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-apache-node26) +| [thecodingmachine/php:8.4-v5-fpm](Dockerfile.fpm) | `8.4.x` | fat | fpm | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-fpm.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-fpm) +| [thecodingmachine/php:8.4-v5-fpm-node22](Dockerfile.fpm.node) | `8.4.x` | fat | fpm | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-fpm-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-fpm-node22) +| [thecodingmachine/php:8.4-v5-fpm-node24](Dockerfile.fpm.node) | `8.4.x` | fat | fpm | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-fpm-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-fpm-node24) +| [thecodingmachine/php:8.4-v5-fpm-node26](Dockerfile.fpm.node) | `8.4.x` | fat | fpm | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-fpm-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-fpm-node26) +| [thecodingmachine/php:8.4-v5-cli](Dockerfile.cli) | `8.4.x` | fat | cli | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-cli.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-cli) +| [thecodingmachine/php:8.4-v5-cli-node22](Dockerfile.cli.node) | `8.4.x` | fat | cli | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-cli-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-cli-node22) +| [thecodingmachine/php:8.4-v5-cli-node24](Dockerfile.cli.node) | `8.4.x` | fat | cli | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-cli-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-cli-node24) +| [thecodingmachine/php:8.4-v5-cli-node26](Dockerfile.cli.node) | `8.4.x` | fat | cli | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-cli-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-cli-node26) +| [thecodingmachine/php:8.4-v5-slim-apache](Dockerfile.slim.apache) | `8.4.x` | slim | apache | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-slim-apache.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-slim-apache) +| [thecodingmachine/php:8.4-v5-slim-fpm](Dockerfile.slim.fpm) | `8.4.x` | slim | fpm | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-slim-fpm.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-slim-fpm) +| [thecodingmachine/php:8.4-v5-slim-cli](Dockerfile.slim.cli) | `8.4.x` | slim | cli | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.4-v5-slim-cli.svg)](https://microbadger.com/images/thecodingmachine/php:8.4-v5-slim-cli) +| [thecodingmachine/php:8.3-v5-apache](Dockerfile.apache) | `8.3.x` | fat | apache | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-apache.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-apache) +| [thecodingmachine/php:8.3-v5-apache-node22](Dockerfile.apache.node) | `8.3.x` | fat | apache | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-apache-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-apache-node22) +| [thecodingmachine/php:8.3-v5-apache-node24](Dockerfile.apache.node) | `8.3.x` | fat | apache | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-apache-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-apache-node24) +| [thecodingmachine/php:8.3-v5-apache-node26](Dockerfile.apache.node) | `8.3.x` | fat | apache | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-apache-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-apache-node26) +| [thecodingmachine/php:8.3-v5-fpm](Dockerfile.fpm) | `8.3.x` | fat | fpm | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-fpm.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-fpm) +| [thecodingmachine/php:8.3-v5-fpm-node22](Dockerfile.fpm.node) | `8.3.x` | fat | fpm | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-fpm-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-fpm-node22) +| [thecodingmachine/php:8.3-v5-fpm-node24](Dockerfile.fpm.node) | `8.3.x` | fat | fpm | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-fpm-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-fpm-node24) +| [thecodingmachine/php:8.3-v5-fpm-node26](Dockerfile.fpm.node) | `8.3.x` | fat | fpm | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-fpm-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-fpm-node26) +| [thecodingmachine/php:8.3-v5-cli](Dockerfile.cli) | `8.3.x` | fat | cli | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-cli.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-cli) +| [thecodingmachine/php:8.3-v5-cli-node22](Dockerfile.cli.node) | `8.3.x` | fat | cli | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-cli-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-cli-node22) +| [thecodingmachine/php:8.3-v5-cli-node24](Dockerfile.cli.node) | `8.3.x` | fat | cli | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-cli-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-cli-node24) +| [thecodingmachine/php:8.3-v5-cli-node26](Dockerfile.cli.node) | `8.3.x` | fat | cli | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-cli-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-cli-node26) +| [thecodingmachine/php:8.3-v5-slim-apache](Dockerfile.slim.apache) | `8.3.x` | slim | apache | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-slim-apache.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-slim-apache) +| [thecodingmachine/php:8.3-v5-slim-fpm](Dockerfile.slim.fpm) | `8.3.x` | slim | fpm | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-slim-fpm.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-slim-fpm) +| [thecodingmachine/php:8.3-v5-slim-cli](Dockerfile.slim.cli) | `8.3.x` | slim | cli | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.3-v5-slim-cli.svg)](https://microbadger.com/images/thecodingmachine/php:8.3-v5-slim-cli) +| [thecodingmachine/php:8.2-v5-apache](Dockerfile.apache) | `8.2.x` | fat | apache | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-apache.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-apache) +| [thecodingmachine/php:8.2-v5-apache-node22](Dockerfile.apache.node) | `8.2.x` | fat | apache | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-apache-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-apache-node22) +| [thecodingmachine/php:8.2-v5-apache-node24](Dockerfile.apache.node) | `8.2.x` | fat | apache | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-apache-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-apache-node24) +| [thecodingmachine/php:8.2-v5-apache-node26](Dockerfile.apache.node) | `8.2.x` | fat | apache | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-apache-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-apache-node26) +| [thecodingmachine/php:8.2-v5-fpm](Dockerfile.fpm) | `8.2.x` | fat | fpm | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-fpm.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-fpm) +| [thecodingmachine/php:8.2-v5-fpm-node22](Dockerfile.fpm.node) | `8.2.x` | fat | fpm | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-fpm-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-fpm-node22) +| [thecodingmachine/php:8.2-v5-fpm-node24](Dockerfile.fpm.node) | `8.2.x` | fat | fpm | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-fpm-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-fpm-node24) +| [thecodingmachine/php:8.2-v5-fpm-node26](Dockerfile.fpm.node) | `8.2.x` | fat | fpm | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-fpm-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-fpm-node26) +| [thecodingmachine/php:8.2-v5-cli](Dockerfile.cli) | `8.2.x` | fat | cli | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-cli.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-cli) +| [thecodingmachine/php:8.2-v5-cli-node22](Dockerfile.cli.node) | `8.2.x` | fat | cli | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-cli-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-cli-node22) +| [thecodingmachine/php:8.2-v5-cli-node24](Dockerfile.cli.node) | `8.2.x` | fat | cli | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-cli-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-cli-node24) +| [thecodingmachine/php:8.2-v5-cli-node26](Dockerfile.cli.node) | `8.2.x` | fat | cli | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-cli-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-cli-node26) +| [thecodingmachine/php:8.2-v5-slim-apache](Dockerfile.slim.apache) | `8.2.x` | slim | apache | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-slim-apache.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-slim-apache) +| [thecodingmachine/php:8.2-v5-slim-fpm](Dockerfile.slim.fpm) | `8.2.x` | slim | fpm | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-slim-fpm.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-slim-fpm) +| [thecodingmachine/php:8.2-v5-slim-cli](Dockerfile.slim.cli) | `8.2.x` | slim | cli | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.2-v5-slim-cli.svg)](https://microbadger.com/images/thecodingmachine/php:8.2-v5-slim-cli) +| [thecodingmachine/php:8.1-v5-apache](Dockerfile.apache) | `8.1.x` | fat | apache | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-apache.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-apache) +| [thecodingmachine/php:8.1-v5-apache-node20](Dockerfile.apache.node) | `8.1.x` | fat | apache | `20.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-apache-node20.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-apache-node20) +| [thecodingmachine/php:8.1-v5-apache-node22](Dockerfile.apache.node) | `8.1.x` | fat | apache | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-apache-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-apache-node22) +| [thecodingmachine/php:8.1-v5-apache-node24](Dockerfile.apache.node) | `8.1.x` | fat | apache | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-apache-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-apache-node24) +| [thecodingmachine/php:8.1-v5-apache-node26](Dockerfile.apache.node) | `8.1.x` | fat | apache | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-apache-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-apache-node26) +| [thecodingmachine/php:8.1-v5-fpm](Dockerfile.fpm) | `8.1.x` | fat | fpm | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-fpm.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-fpm) +| [thecodingmachine/php:8.1-v5-fpm-node20](Dockerfile.fpm.node) | `8.1.x` | fat | fpm | `20.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-fpm-node20.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-fpm-node20) +| [thecodingmachine/php:8.1-v5-fpm-node22](Dockerfile.fpm.node) | `8.1.x` | fat | fpm | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-fpm-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-fpm-node22) +| [thecodingmachine/php:8.1-v5-fpm-node24](Dockerfile.fpm.node) | `8.1.x` | fat | fpm | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-fpm-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-fpm-node24) +| [thecodingmachine/php:8.1-v5-fpm-node26](Dockerfile.fpm.node) | `8.1.x` | fat | fpm | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-fpm-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-fpm-node26) +| [thecodingmachine/php:8.1-v5-cli](Dockerfile.cli) | `8.1.x` | fat | cli | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-cli.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-cli) +| [thecodingmachine/php:8.1-v5-cli-node20](Dockerfile.cli.node) | `8.1.x` | fat | cli | `20.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-cli-node20.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-cli-node20) +| [thecodingmachine/php:8.1-v5-cli-node22](Dockerfile.cli.node) | `8.1.x` | fat | cli | `22.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-cli-node22.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-cli-node22) +| [thecodingmachine/php:8.1-v5-cli-node24](Dockerfile.cli.node) | `8.1.x` | fat | cli | `24.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-cli-node24.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-cli-node24) +| [thecodingmachine/php:8.1-v5-cli-node26](Dockerfile.cli.node) | `8.1.x` | fat | cli | `26.x` | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-cli-node26.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-cli-node26) +| [thecodingmachine/php:8.1-v5-slim-apache](Dockerfile.slim.apache) | `8.1.x` | slim | apache | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-slim-apache.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-slim-apache) +| [thecodingmachine/php:8.1-v5-slim-fpm](Dockerfile.slim.fpm) | `8.1.x` | slim | fpm | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-slim-fpm.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-slim-fpm) +| [thecodingmachine/php:8.1-v5-slim-cli](Dockerfile.slim.cli) | `8.1.x` | slim | cli | *N/A* | [![](https://images.microbadger.com/badges/image/thecodingmachine/php:8.1-v5-slim-cli.svg)](https://microbadger.com/images/thecodingmachine/php:8.1-v5-slim-cli) @@ -158,6 +176,12 @@ Example with PHP-FPM: $ docker run -p 9000:9000 --rm --name my-php-fpm -v "$PWD":/var/www/html thecodingmachine/php:8.4-v5-fpm ``` +Example with PHP-FPM and its built-in Apache (in the same container): + +```bash +$ docker run -p 80:80 --rm --name my-apache-fpm-app -e PHP_FPM_WEB_SERVER=apache -v "$PWD":/var/www/html thecodingmachine/php:8.4-v5-fpm +``` + Example with Apache + Node 24.x in a Dockerfile: **Dockerfile** @@ -312,10 +336,49 @@ you are using: | apache | `/var/www/html` | | fpm | `/var/www/html` | +## Built-in Apache of the fpm variant + +With `PHP_FPM_WEB_SERVER=apache`, the *fpm* variant runs Apache (`mpm_event`) in front of PHP-FPM, in the same +container, with the Apache features of the *apache* variant (`.htaccess`, `APACHE_DOCUMENT_ROOT`, `APACHE_EXTENSION_*`). +The number of PHP workers is configured independently (see [PHP-FPM settings](#php-fpm-settings)), and +`APACHE_PROXY_TIMEOUT` sets how long Apache waits for PHP-FPM (`300` seconds by default). + +The [fpm variant documentation](docs/fpm.md) details +its advantages, the constraints of PHP-FPM (number of workers and memory, timeouts, `php_value` in `.htaccess`), +how to use your own web server instead (nginx...) and how to migrate from the *apache* variant. + +## PHP-FPM settings + +For the *fpm* variant, the PHP-FPM process manager can be configured with environment variables +(the defaults are the ones of the Ubuntu package): + +| Environment variable | `php-fpm.conf` setting | Default | +|--------------------------------|-------------------------|-----------| +| `PHP_FPM_PM` | `pm` | `dynamic` | +| `PHP_FPM_PM_MAX_CHILDREN` | `pm.max_children` | `5` | +| `PHP_FPM_PM_START_SERVERS` | `pm.start_servers` | `2` | +| `PHP_FPM_PM_MIN_SPARE_SERVERS` | `pm.min_spare_servers` | `1` | +| `PHP_FPM_PM_MAX_SPARE_SERVERS` | `pm.max_spare_servers` | `3` | +| `PHP_FPM_PM_MAX_REQUESTS` | `pm.max_requests` | `0` | +| `PHP_FPM_ACCESS_LOG` | `access.log` | `/proc/self/fd/2` | + +The `php-fpm-healthcheck` command checks that PHP-FPM answers (on its `/ping` endpoint). You can use it as a Docker +healthcheck or as a Kubernetes probe: + +```yml +services: + my_app: + image: thecodingmachine/php:8.4-v5-fpm + healthcheck: + test: ["CMD", "php-fpm-healthcheck"] +``` + +The *fpm* variant (with or without Apache) is stopped gracefully (`SIGQUIT`): requests being processed are completed before the container stops. + ## Changing Apache document root -For the *apache* variant, you can change the document root of Apache (i.e. your "public" directory) by using the +For the *apache* variant and the built-in Apache of the *fpm* variant, you can change the document root of Apache (i.e. your "public" directory) by using the `APACHE_DOCUMENT_ROOT` variable: ```bash @@ -358,6 +421,8 @@ APACHE_EXTENSIONS="dav ssl" **Apache modules enabled by default:** `access_compat` `alias` `auth_basic` `authn_core` `authn_file` `authz_core` `authz_host` `authz_user` `autoindex` `deflate` `dir` `env` `expires` `filter` `mime` `mpm_prefork` `negotiation` `php8.4 (depend of your active version)` `reqtimeout` `rewrite` `setenvif` `status` +For the built-in Apache of the *fpm* variant, `mpm_event` `proxy` `proxy_fcgi` are enabled instead of `mpm_prefork` and `php8.4` (`mod_php` is not available). + **Apache modules available:** `access_compat` `actions` `alias` `allowmethods` `asis` `auth_basic` `auth_digest` `auth_form` `authn_anon` `authn_core` `authn_dbd` `authn_dbm` `authn_file` `authn_socache` `authnz_fcgi` `authnz_ldap` `authz_core` `authz_dbd` `authz_dbm` `authz_groupfile` `authz_host` `authz_owner` `authz_user` `autoindex` `brotli` `buffer` `cache` `cache_disk` `cache_socache` `cern_meta` `cgi` `cgid` `charset_lite` `data` `dav` `dav_fs` `dav_lock` `dbd` `deflate` `dialup` `dir` `dump_io` `echo` `env` `ext_filter` `expires` `file_cache` `filter` `headers` `heartbeat` `heartmonitor` `http2` `ident` `imagemap` `include` `info` `lbmethod_bybusyness` `lbmethod_byrequests` `lbmethod_bytraffic` `lbmethod_heartbeat` `ldap` `log_debug` `log_forensic` `lua` `macro` `md` `mime` `mime_magic` `mpm_event` `mpm_prefork` `mpm_worker` `negotiation` `php8.4 (depend of your active version)` `proxy` `proxy_ajp` `proxy_balancer` `proxy_connect` `proxy_express` `proxy_fcgi` `proxy_fdpass` `proxy_ftp` `proxy_hcheck` `proxy_html` `proxy_http` `proxy_http2` `proxy_scgi` `proxy_wstunnel` `ratelimit` `reflector` `remoteip` `reqtimeout` `request` `rewrite` `sed` `session` `session_cookie` `session_crypto` `session_dbd` `setenvif` `slotmem_plain` `slotmem_shm` `socache_dbm` `socache_memcache` `socache_redis` `socache_shmcb` `speling` `ssl` `status` `substitute` `suexec` `unique_id` `userdir` `usertrack` `vhost_alias` `xml2enc` This list can be outdated, you can verify by executing : `docker run --rm -it thecodingmachine/php:8.4-v5-slim-apache a2enmod` diff --git a/benchmarks/fpm-apache/.gitignore b/benchmarks/fpm-apache/.gitignore new file mode 100644 index 00000000..835c0208 --- /dev/null +++ b/benchmarks/fpm-apache/.gitignore @@ -0,0 +1,2 @@ +app/assets/ +results/ diff --git a/benchmarks/fpm-apache/README.md b/benchmarks/fpm-apache/README.md new file mode 100644 index 00000000..c9d82de4 --- /dev/null +++ b/benchmarks/fpm-apache/README.md @@ -0,0 +1,31 @@ +# Benchmark: `apache` (mod_php) vs `fpm` with its built-in Apache + +Both variants run the same application with their default Apache settings and the same resources (2 CPUs, 2 GB), +and receive exactly the same load: a constant number of pages per second. A page is a PHP request (~3 ms of CPU and +20 ms of I/O) and 10 static assets, like a browser. A variant handles a rate when its p95 stays under 100 ms and its +p99 under 1 s, without error. + +## Results (PHP 8.4, amd64) + +| | `apache` (mod_php) | `fpm` + built-in Apache | +|---|---|---| +| Pages per second handled | 10 | **30** | +| PHP requests per second handled (no assets) | < 100 | **200** | +| Memory | 280-385 MiB | **80-100 MiB** | + +The `fpm` variant serves **2 to 3 times more traffic with 4 times less memory**. + +With `mod_php`, every connection holds an Apache process embedding PHP, including idle keep-alive connections (a +browser opens up to 6): from 15 pages/s the 150 processes are exhausted and requests wait for up to 30 s, while the +CPU is almost idle. With PHP-FPM, Apache (`mpm_event`) keeps the connections with a few threads and only PHP +requests use the 20 PHP workers. + +Single run on a developer machine: the orders of magnitude are reliable, not the exact values. + +## Running it + +Requires Docker only ([k6](https://k6.io/) runs in a container): + +```bash +./run.sh 8.4 +``` diff --git a/benchmarks/fpm-apache/app/index.php b/benchmarks/fpm-apache/app/index.php new file mode 100644 index 00000000..f2ed4fa6 --- /dev/null +++ b/benchmarks/fpm-apache/app/index.php @@ -0,0 +1,14 @@ +'; +for ($i = 1; $i <= 10; $i++) { + $html .= ''; +} +$html .= '' . str_repeat('

' . $data[array_rand($data)] . '

', 200) . ''; +echo $html; diff --git a/benchmarks/fpm-apache/run.sh b/benchmarks/fpm-apache/run.sh new file mode 100755 index 00000000..eccad43b --- /dev/null +++ b/benchmarks/fpm-apache/run.sh @@ -0,0 +1,156 @@ +#!/usr/bin/env bash +# Compares the "apache" variant (mod_php, mpm_prefork) and the "fpm" variant with its built-in Apache +# (PHP_FPM_WEB_SERVER=apache: mpm_event + PHP-FPM), labelled "fpm-apache". +# +# Both variants receive exactly the same load: a constant number of pages per second (open model), +# for several rates. The capacity of a variant is the highest rate served with a page p95 under +# MAX_P95 ms and a p99 under MAX_P99 ms (no request stuck), without error nor dropped page. +# +# Usage: ./run.sh [php version] +# Env: RATES, PHP_RATES, DURATION, MAX_P95, MAX_P99, CPUS, MEMORY, FPM_MAX_CHILDREN, REPO, TAG_PREFIX, +# SUMMARY_ONLY=1 (only print the summary of the previous run) +set -e +cd "$(dirname "$0")" + +PHP_VERSION="${1:-8.4}" +REPO="${REPO:-thecodingmachine/php}" +TAG_PREFIX="${TAG_PREFIX:-}" +RATES="${RATES:-10 15 20 30 40 60 80}" +PHP_RATES="${PHP_RATES:-100 200 300}" +DURATION="${DURATION:-30s}" +MAX_P95="${MAX_P95:-100}" +MAX_P99="${MAX_P99:-1000}" +CPUS="${CPUS:-2}" +MEMORY="${MEMORY:-2g}" +FPM_MAX_CHILDREN="${FPM_MAX_CHILDREN:-20}" +NETWORK="bench-fpm-apache" +RESULTS="results" +VARIANTS="apache fpm-apache" + +if [[ "$SUMMARY_ONLY" != "1" ]]; then +mkdir -p "$RESULTS" app/assets +for i in $(seq 1 10); do + [[ -f "app/assets/asset$i.css" ]] || head -c 30000 /dev/urandom | base64 > "app/assets/asset$i.css" +done +docker network create "$NETWORK" > /dev/null 2>&1 || true + +k6() { + docker run --rm -u "$(id -u)" --network "$NETWORK" -v "$PWD":/bench grafana/k6 run -q "$@" /bench/scenario.js +} + +# run_level +run_level() { + local variant="$1" container="$2" result="$3"; shift 3 + # Sample memory and CPU of the server during the run + (while true; do + docker stats --no-stream --format '{{.MemUsage}};{{.CPUPerc}}' "$container" 2>/dev/null || break + done) > "$RESULTS/${variant}-${result}-stats.log" & + local stats_pid=$! + k6 -e DURATION="$DURATION" "$@" \ + --summary-export "/bench/$RESULTS/${variant}-${result}-summary.json" > "$RESULTS/${variant}-${result}-k6.log" 2>&1 || true + kill "$stats_pid" 2>/dev/null || true + wait "$stats_pid" 2>/dev/null || true + # Let idle connections and processes settle between levels + sleep 10 +} + +bench() { + local variant="$1"; local image_variant="$2"; shift 2 + local name="bench-${variant}" + docker rm -f "$name" > /dev/null 2>&1 || true + docker run -d --name "$name" --network "$NETWORK" --network-alias app \ + --cpus "$CPUS" --memory "$MEMORY" \ + -e TEMPLATE_PHP_INI=production "$@" \ + -v "$PWD/app":/var/www/html:ro \ + "${REPO}:${TAG_PREFIX}${PHP_VERSION}-v5-slim-${image_variant}" > /dev/null + sleep 5 + # Warm up (opcache, process spawning) + k6 -e RATE=5 -e DURATION=10s > /dev/null 2>&1 + for rate in $RATES; do + run_level "$variant" "$name" "page-${rate}" -e RATE="$rate" + done + for rate in $PHP_RATES; do + run_level "$variant" "$name" "php-${rate}" -e RATE="$rate" -e PHP_ONLY=1 + done + docker logs "$name" > "$RESULTS/${variant}-server.log" 2>&1 + docker rm -f "$name" > /dev/null +} + +bench apache apache +bench fpm-apache fpm -e PHP_FPM_WEB_SERVER=apache -e PHP_FPM_PM=static -e PHP_FPM_PM_MAX_CHILDREN="$FPM_MAX_CHILDREN" +docker network rm "$NETWORK" > /dev/null +fi + +# |-- Summary ---------------------------------------------------------------- +# metrics : p50, p95, p99, max, errors (%), dropped +metrics() { + jq -r '[ + (.metrics["group_duration{group:::page}"]["p(50)"] | floor), + (.metrics["group_duration{group:::page}"]["p(95)"] | floor), + (.metrics["group_duration{group:::page}"]["p(99)"] | floor), + (.metrics["group_duration{group:::page}"].max | floor), + (.metrics.http_req_failed.value * 1000 | floor / 10), + (.metrics.dropped_iterations.count // 0) + ] | map(tostring) | join(" ")' "$1" +} +max_mib() { + cut -d';' -f1 "$1" | cut -d'/' -f1 | sed 's/ //g' | awk ' + /GiB$/ {v=$0; sub(/GiB/,"",v); v*=1024} + /MiB$/ {v=$0; sub(/MiB/,"",v)} + /KiB$/ {v=$0; sub(/KiB/,"",v); v/=1024} + {if (v>m) m=v} END {printf "%d", m}' +} +avg_cpu() { + cut -d';' -f2 "$1" | tr -d '%' | awk '$1>1 {s+=$1; n++} END {printf "%d", (n ? s/n : 0)}' +} +# table