When containerizing PHP-FPM applications, one common pain point is handling logs in a Docker-native way. While writing logs to files inside the container works, it violates the 12-factor app principle of treating logs as event streams.
The symlink approach that works for Nginx doesn't reliably work for PHP-FPM due to how the service handles file descriptors. Here's why the common solution fails:
# This often doesn't work as expected
RUN ln -sf /dev/stdout /var/log/fpm-access.log
RUN ln -sf /dev/stderr /var/log/fpm-php.www.log
Solution 1: Direct stdout/stderr Configuration
The most reliable method is modifying the PHP-FPM pool configuration:
# /etc/php5/fpm/pool.d/www.conf
[www]
; Replace existing log configuration with:
access.log = /proc/self/fd/2
catch_workers_output = yes
php_admin_value[error_log] = /proc/self/fd/2
php_admin_flag[log_errors] = on
Solution 2: Using Docker Logging Drivers
For advanced use cases, configure Docker's logging driver to capture the file logs:
# docker-compose.yml example
services:
php-fpm:
image: your-php-fpm-image
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
If logs still don't appear in docker logs
, check:
- Filesystem permissions on /proc/self/fd/
- PHP-FPM worker process ownership
- Docker container user namespace configuration
Here's a complete Dockerfile implementation:
FROM php:8.2-fpm
RUN apt-get update && apt-get install -y \
&& docker-php-ext-install pdo_mysql
# Configure PHP-FPM logging
RUN echo "access.log = /proc/self/fd/2" >> /usr/local/etc/php-fpm.d/docker.conf \
&& echo "catch_workers_output = yes" >> /usr/local/etc/php-fpm.d/docker.conf \
&& echo "php_admin_value[error_log] = /proc/self/fd/2" >> /usr/local/etc/php-fpm.d/docker.conf \
&& echo "php_admin_flag[log_errors] = on" >> /usr/local/etc/php-fpm.d/docker.conf
# Ensure proper permissions
RUN chmod -R 777 /proc/self/fd/
For centralized logging systems:
[www]
access.log = syslog
slowlog = syslog
php_admin_value[error_log] = syslog
When running PHP-FPM in Docker containers, many developers face difficulties getting logs to appear in docker logs
output. The standard approach of writing logs to files in /var/log
works, but breaks Docker's logging best practices.
The traditional PHP-FPM configuration writes logs to physical files:
access.log = /var/log/fpm-access.log
php_admin_value[error_log] = /var/log/fpm-php.www.log
While this works for accessing logs via shell, it prevents Docker from automatically collecting and forwarding these logs.
Here's the proper way to configure PHP-FPM for Docker logging:
# In your Dockerfile
RUN sed -i '/^;catch_workers_output/ccatch_workers_output = yes' /etc/php5/fpm/pool.d/www.conf && \
sed -i '/^;access.log/caccess.log = /proc/self/fd/2' /etc/php5/fpm/pool.d/www.conf && \
sed -i '/^;php_admin_value[error_log]/cphp_admin_value[error_log] = /proc/self/fd/2' /etc/php5/fpm/pool.d/www.conf
1. Use /proc/self/fd/2
(stderr) instead of /dev/stderr
for better compatibility
2. Ensure catch_workers_output
is set to yes
3. For separate access and error logs:
access.log = /proc/self/fd/1
php_admin_value[error_log] = /proc/self/fd/2
Here's a full working example:
FROM php:5-fpm
# Configure PHP-FPM logging
RUN echo "catch_workers_output = yes" >> /usr/local/etc/php-fpm.d/www.conf && \
echo "access.log = /proc/self/fd/2" >> /usr/local/etc/php-fpm.d/www.conf && \
echo "php_admin_value[error_log] = /proc/self/fd/2" >> /usr/local/etc/php-fpm.d/www.conf && \
echo "php_admin_flag[log_errors] = on" >> /usr/local/etc/php-fpm.d/www.conf
# Additional PHP configuration
RUN echo "display_errors = stderr" >> /usr/local/etc/php/php.ini
EXPOSE 9000
CMD ["php-fpm"]
If logs still don't appear in docker logs
:
- Verify the PHP-FPM worker processes have permission to write to stdout/stderr
- Check if any other configuration is overriding your settings
- Test with a minimal configuration to isolate the issue
For PHP versions before 5.3, you might need to use symbolic links:
RUN mkfifo /var/log/fpm-access.log && \
mkfifo /var/log/fpm-php.www.log && \
chown www-data:www-data /var/log/fpm-*.log && \
(tail -f /var/log/fpm-access.log >> /proc/self/fd/1 &) && \
(tail -f /var/log/fpm-php.www.log >> /proc/self/fd/2 &)