Configuration

PHP settings

Named variables for the common php.ini and PHP-FPM settings, and generic overrides for everything else.

Named variables

The frequently changed settings have their own variables with safe defaults. These are the ones you will set most often:

docker run --rm -d -p 8080:8080 \
  -e NGINX_PORT=8080 \
  -e PHP_MEMORY_LIMIT=512M \
  -e PHP_POST_MAX_SIZE=64M \
  -e PHP_UPLOAD_MAX_FILESIZE=64M \
  -e PHP_MAX_EXECUTION_TIME=120 \
  -e PHP_DATE_TIMEZONE=Europe/London \
  -e OPCACHE_ENABLE=1 \
  adamrollogi/php-nginx:8.4

The complete list, including security and OPcache settings, is in the environment variable reference.

Nginx's client_max_body_size follows PHP_POST_MAX_SIZE, so raising the PHP upload limits is enough; you do not need to touch Nginx.

Any php.ini setting

Any environment variable whose name starts with php. is appended to php.ini as <setting> = <value> after the templated settings, so it always wins.

-e php.max_input_vars=5000
-e php.realpath_cache_size=8M
-e php.session.gc_maxlifetime=7200
-e php.xdebug.max_nesting_level=512

This works in every image and applies equally to the CLI and to PHP-FPM, because both read the same rendered php.ini.

Any PHP-FPM setting

Two more prefixes cover PHP-FPM:

PrefixTargetExample
fpm.pool.<setting>the [www] pool-e fpm.pool.pm.max_children=50
fpm.global.<setting>the [global] section-e fpm.global.log_level=debug

Bracketed keys work too. This is how you pin a setting for FPM only, so that it cannot be changed by ini_set():

-e "fpm.pool.php_admin_value[memory_limit]=512M"
-e "fpm.pool.php_admin_flag[display_errors]=off"
Overrides are applied verbatim. pm.max_children must stay above pm.max_spare_servers (default 10) or FPM refuses to start, and the container logs the exact error.

Multi-line values are not supported.

Docker Compose

Keys with dots are fine in Compose environment maps:

compose.yaml
services:
  app:
    image: adamrollogi/php-nginx:8.4
    environment:
      PHP_MEMORY_LIMIT: 256M
      php.date.timezone: Europe/London
      php.session.cookie_lifetime: "0"
      fpm.pool.pm.max_children: "40"
      fpm.pool.pm.start_servers: "8"
      fpm.pool.pm.min_spare_servers: "4"
      fpm.pool.pm.max_spare_servers: "12"

Where the files end up

FileContent
/run/php/php.iniRendered from php.ini.template, then php.* overrides appended.
/run/php/php-fpm.conf[global] with the error log, then fpm.global.* overrides, then the pool include.
/run/php/php-fpm.d/www.confRendered pool, then fpm.pool.* overrides appended.

The stock /etc/php8x/ directory is never modified. See Users and permissions for why.

OPcache in production

-e OPCACHE_ENABLE=1
-e OPCACHE_VALIDATE_TIMESTAMPS=0     # code is immutable inside the image
-e OPCACHE_MEMORY_CONSUMPTION=256
-e OPCACHE_MAX_ACCELERATED_FILES=20000

From PHP 8.5, OPcache is compiled into PHP rather than installed as a separate package. The variables work the same way.

Sending mail

There is no MTA in the image. Point PHP_SENDMAIL_PATH at a relay binary you add in a derived image, for example msmtp:

FROM adamrollogi/php-nginx:8.4
USER root
RUN apk add --no-cache msmtp
USER appuser
ENV PHP_SENDMAIL_PATH="/usr/bin/msmtp -t"