diff --git a/CHANGELOG.md b/CHANGELOG.md index c4e5076f..903ed355 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,16 @@ ### Minor changes +* **2026-10-19** + * 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) + * **2026-10-12** * The README only describes the images and links to the documentation of each topic in the `docs` directory (extensions, php.ini, variants, processes, debugging, advanced features, contributing) * Add `APACHE_HTTP_PORT` and `APACHE_HTTPS_PORT` to change the ports Apache listens on (e.g. unprivileged ports) diff --git a/Dockerfile.slim.apache b/Dockerfile.slim.apache index a5c418dd..2c498b07 100644 --- a/Dockerfile.slim.apache +++ b/Dockerfile.slim.apache @@ -162,6 +162,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 @@ -201,20 +202,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 @@ -231,9 +231,11 @@ RUN sed -ri -e 's/^Listen 80$/Listen ${APACHE_HTTP_PORT}/' -e 's/^(\s*)Listen 44 sed -i 's///' /etc/apache2/sites-available/000-default.conf && \ sed -i 's///' /etc/apache2/sites-available/default-ssl.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 # |-------------------------------------------------------------------------- @@ -326,6 +328,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 @@ -342,8 +346,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 885fa379..9025cdce 100644 --- a/Dockerfile.slim.cli +++ b/Dockerfile.slim.cli @@ -244,6 +244,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 COPY utils/supervise.sh /usr/local/bin/supervise.sh diff --git a/Dockerfile.slim.fpm b/Dockerfile.slim.fpm index 2fe6690e..f279cc99 100644 --- a/Dockerfile.slim.fpm +++ b/Dockerfile.slim.fpm @@ -162,10 +162,88 @@ 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 + +ENV APACHE_HTTP_PORT=80 \ + APACHE_HTTPS_PORT=443 + +RUN sed -ri -e 's/^Listen 80$/Listen ${APACHE_HTTP_PORT}/' -e 's/^(\s*)Listen 443$/\1Listen ${APACHE_HTTPS_PORT}/' /etc/apache2/ports.conf && \ + sed -i 's///' /etc/apache2/sites-available/000-default.conf && \ + sed -i 's///' /etc/apache2/sites-available/default-ssl.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/* @@ -173,8 +251,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 @@ -261,6 +356,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 COPY utils/supervise.sh /usr/local/bin/supervise.sh @@ -271,6 +369,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 567e17d7..84880fd6 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 - All images come with [Composer](https://getcomposer.org/) installed - All variants can be installed with or without NodeJS (if you need to build your static assets). @@ -25,84 +43,84 @@ See the [documentation](#documentation) for all the features. | 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) @@ -160,6 +178,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** @@ -180,7 +204,8 @@ Most features are configured with environment variables: |----------------------------------------------------|------------------------------------------------------------------------------------------------|--------------------------------------------------------------------| | [PHP extensions](docs/extensions.md) | Extensions of the slim and fat images, enabling them, compiling them in a slim image | `PHP_EXTENSION_*`, `PHP_EXTENSIONS` | | [PHP configuration](docs/php-configuration.md) | Base `php.ini` file and `php.ini` parameters | `TEMPLATE_PHP_INI`, `PHP_INI_*` | -| [Variants](docs/variants.md) | *cli*, *apache* (document root, ports, modules, user) and *fpm* | `APACHE_DOCUMENT_ROOT`, `APACHE_HTTP_PORT`, `APACHE_EXTENSION_*` | +| [Variants](docs/variants.md) | *cli*, *apache* (document root, ports, modules, user) and *fpm* (built-in Apache, PHP-FPM) | `APACHE_DOCUMENT_ROOT`, `APACHE_EXTENSION_*`, `PHP_FPM_WEB_SERVER` | +| [Serving with the fpm variant](docs/fpm.md) | Built-in Apache or your own web server, constraints of PHP-FPM, migration from *apache* | `PHP_FPM_WEB_SERVER`, `PHP_FPM_PM_*` | | [Processes](docs/processes.md) | Startup commands, cron jobs and daemons run along with the main command | `STARTUP_COMMAND_*`, `CRON_*`, `DAEMON_*` | | [Debugging and profiling](docs/debugging.md) | Xdebug and Blackfire | `PHP_EXTENSION_XDEBUG`, `XDEBUG_CLIENT_HOST`, `BLACKFIRE_AGENT` | | [Advanced features](docs/advanced.md) | Permissions, NodeJS, Composer version, locales, SSH keys, Kubernetes | `DOCKER_USER`, `COMPOSER_VERSION`, `LOCALES` | 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