Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`)
Expand Down
18 changes: 12 additions & 6 deletions Dockerfile.slim.apache
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -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
# |--------------------------------------------------------------------------
Expand Down Expand Up @@ -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
Expand All @@ -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
# |--------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions Dockerfile.slim.cli
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
111 changes: 110 additions & 1 deletion Dockerfile.slim.fpm
Original file line number Diff line number Diff line change
Expand Up @@ -161,19 +161,107 @@ 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/*

# Let's remove the default PHP-FPM php.ini file (it will be copied from TEMPLATE_PHP_INI)
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
Expand Down Expand Up @@ -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

Expand All @@ -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"]
Expand Down
Loading