How to Configure pm.max_children for PHP-FPM in Docker: Solving “server reached pm.max_children setting” Warnings


1 views

Many developers encounter this frustrating scenario where PHP-FPM warnings persist despite updating php.ini. The critical detail often missed is that PHP-FPM has its own configuration files that override php.ini settings for process management.

For Dockerized PHP-FPM setups, you need to modify the pool configuration file, typically found at:

/usr/local/etc/php-fpm.d/www.conf

Here's how to verify if this file exists in your container:

docker exec -it your_php_container_name ls /usr/local/etc/php-fpm.d/

You have two primary approaches:

Method 1: Direct File Mounting

Update your docker-compose.yml to mount a custom www.conf:

services:
  pi_php:
    build: ./php
    volumes:
      - ../src:/src
      - ./php/config/php.ini:/usr/local/etc/php/php.ini
      - ./php/config/www.conf:/usr/local/etc/php-fpm.d/www.conf

Method 2: Using Dockerfile

Create a custom www.conf file and copy it during build:

FROM php:fpm
COPY ./config/www.conf /usr/local/etc/php-fpm.d/www.conf

Here's an optimized configuration for medium traffic:

[www]
user = www-data
group = www-data

listen = 9000
listen.owner = www-data
listen.group = www-data

pm = dynamic
pm.max_children = 40
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 500

After making changes:

# Restart your PHP-FPM container
docker-compose restart pi_php

# Check active processes
docker exec -it docker_pi_php_1 ps aux | grep php-fpm

# Verify settings
docker exec -it docker_pi_php_1 php-fpm -tt

Use this formula based on your server resources:

pm.max_children = (Total RAM - (Other Processes RAM)) / (Average PHP Process Size)

Example calculation for a 2GB RAM container:

(2048MB - 512MB) / 40MB ≈ 38 max_children
  • Not restarting PHP-FPM after changes (use kill -USR2 or container restart)
  • Mixing up php.ini and php-fpm.conf settings
  • Setting values too high causing OOM kills
  • Forgetting to account for other services in memory calculations

For more dynamic setups, use env variables in your Dockerfile:

ENV PHP_FPM_PM_MAX_CHILDREN=40
ENV PHP_FPM_PM_START_SERVERS=10

Then in your www.conf:

pm.max_children = ${PHP_FPM_PM_MAX_CHILDREN}
pm.start_servers = ${PHP_FPM_PM_START_SERVERS}

When running PHP-FPM in Docker containers, you might encounter this warning despite updating your php.ini:

[19-Nov-2017 19:24:09] WARNING: [pool www] server reached pm.max_children setting (5), consider raising it

This typically indicates that your PHP-FPM process manager settings aren't being properly applied, even when configuration files appear correct.

PHP-FPM actually has two configuration layers you need to check:

  1. php.ini (global PHP settings)
  2. php-fpm.conf and pool configuration (www.conf)

The pm.max_children setting belongs to the second category and won't be affected by php.ini changes alone.

Here's how to properly configure this in a Docker environment:

1. Create a custom PHP-FPM pool configuration

Add a www.conf file to your PHP container:

[www]
user = www-data
group = www-data
listen = 9000
pm = dynamic
pm.max_children = 40
pm.start_servers = 15
pm.min_spare_servers = 15
pm.max_spare_servers = 25

2. Modify your Dockerfile

Update your PHP Dockerfile to include the custom configuration:

FROM php:7.4-fpm

# Copy custom configuration files
COPY ./config/php.ini /usr/local/etc/php/php.ini
COPY ./config/www.conf /usr/local/etc/php-fpm.d/www.conf

# Rest of your Dockerfile...

3. Verify the configuration

After rebuilding and restarting your containers, verify the settings with:

docker exec -it your_php_container_name php-fpm -tt

This will show all active PHP-FPM configuration values.

If you prefer to keep configurations in docker-compose:

services:
  pi_php:
    build: ./php
    volumes:
      - ../src:/src
      - ./php/config/php.ini:/usr/local/etc/php/php.ini
      - ./php/config/www.conf:/usr/local/etc/php-fpm.d/www.conf

To confirm the settings are active, use:

docker exec -it your_php_container_name ps aux | grep php-fpm

You should see approximately 15 PHP-FPM processes (matching your pm.start_servers value).