PHP E_DEPRECATED messages not being logged as expected on offical php apache image

Hi, I’ve had some trouble with getting E_DEPRECATED log messages using the offical docker images.

I can see E_DEPRECATED messages with php’s display_errors = On, but they do not appear in the logs, I’ve verified that the error reporting level is appropriate, and if I set php’s ‘error_log’ to /var/log/apache2/php_errors.log the messages are written, php syntax errors are logged to docker. Here’s an example docker file with two tests:
docker exec curl 127.0.0.1/dep_err.php

triggers a deprecated error, seen only in the web output’ I expected to see it in the docker logs as well

docker exec curl 127.0.0.1/syntax_err.php throws a php syntax error

triggers a php syntax error, seen in the logs and the web output as expected.

I originally ran into this issue using the offical wordpress apache image, but simplified it down to the following example Dockerfile

FROM php:8.1.10-apache                                                                                                                                                                       
 RUN { \                                                                                                                                                                                     
  echo 'error_reporting = E_ERROR | E_WARNING | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_RECOVERABLE_ERROR | E_DEPRECATED'; \                       
                                                                                                                                                                                             
  echo 'display_errors = On'; \                                                                                                                                                              
  echo 'display_startup_errors = Off'; \                                                                                                                                                     
  echo 'log_errors = On'; \                                                                                                                                                                  
  echo 'error_log = /dev/stderr'; \                                                                                                                                                          
  echo 'log_errors_max_len = 1024'; \                                                                                                                                                        
  echo 'ignore_repeated_errors = On'; \                                                                                                                                                      
  echo 'ignore_repeated_source = Off'; \                                                                                                                                                     
  echo 'html_errors = Off'; \                                                                                                                                                                
 } > /usr/local/etc/php/conf.d/error-logging.ini                                                                                                                                             
                                                                                                                                                                                             
                                                                                                                                                                                             
RUN { \                                                                                                                                                                                      
  echo '<?php '; \                                                                                                                                                                           
  echo '$array = array(1,2,1,3,2,4,3,5);'; \                                                                                                                                                 
  echo 'usort($array, fn($a, $b) => $a > $b); // this should throw a deprecated warning';  \                                                                                                 
  echo 'print_r($array);'; \                                                                                                                                                                 
  echo 'print ini_get("error_reporting");'; \                                                                                                                                                
  echo '?><br><a href="https://maximivanov.github.io/php-error-reporting-calculator/">error_reporting bitmask calculator</a>'; \                                                             
 } > /var/www/html/dep_err.php                                                                                                                                                               
                                                                                                                                                                                             
                                                                                                                                                                                             
                                                                                                                                                                                             
RUN { \                                                                                                                                                                                      
  echo '<?php '; \                                                                                                                                                                           
  echo 'print "syntax error coming up" print "right about here"'; \                                                                                                                          
  } > /var/www/html/syntax_err.php

You are using Apache HTTPD with the PHP module. Let’s say this is the output of ps auxf

root         1  0.0  0.2  81272 23044 ?        Ss   22:02   0:00 apache2 -DFOREGROUND
www-data   334  0.0  0.1  81352 11644 ?        S    22:17   0:00 apache2 -DFOREGROUND
www-data   335  0.0  0.1  81304  8192 ?        S    22:17   0:00 apache2 -DFOREGROUND
www-data   336  0.0  0.1  81304  8192 ?        S    22:17   0:00 apache2 -DFOREGROUND
www-data   337  0.0  0.1  81304  8192 ?        S    22:17   0:00 apache2 -DFOREGROUND
www-data   338  0.0  0.1  81304  8192 ?        S    22:17   0:00 apache2 -DFOREGROUND

The first process is the main HTTPD process that will write to its standard error stream which
/dev/stderr is a link to /dev/1/fd/2. This is what you can see in the output of docker logs.
Then it starts the other processes as www-data.

So I guess It means that you can configure PHP logging and save PHP logs to a file because that file will always be the same, but when you redirect it to /dev/stderr and the process id is 334 that will be linked to /dev/334/fd/2. A different error stream, but you can’t write to the main error stream so it will be the job of the main process to collect the error streams and handle it.

If you want to see those messages in the error log of Apache HTTPD, you should configure Apache HTTPD’s LogLevel to at least “info”. Alternatively, you can also leave the LogLevel as LogLevel warn and add php:info like this

LogLevel warn php:info

Then you will see something like this in the log:

[Thu Sep 22 22:17:51.811091 2022] [php:info] [pid 334] [client 127.0.0.1:42006] PHP Deprecated:  usort(): Returning bool from comparison function is deprecated, return an integer less than, equal to, or greater than zero in /var/www/html/dep_err.php on line 3

which also shows you the process id of the process that sent the log message.

This would be the same without Docker as well, except that without Docker you probably don’t log to the standard error streams.

Official images are coming with some default settings. Many PHP applications would throw E_DEPRECATED, so not everyone wants to see it in the logs by default.

I also want to thank you for sharing a short Dockerfile to reproduce the issue. I needed it because I wasn’t sure about the cause. I hope I could explain it clearly enough :slight_smile:

1 Like

Well described!
Apache logLevel was the bit I was missing, Thanks!

For those looking to catch these E_DEPRECATED messages I added this to my Dockerfile:

RUN { \                                                                                                                                                                                      
  echo 'logLevel warn php:info'; \                                                                                                                                                           
} > /etc/apache2/conf-available/mpm_debug.conf;\                                                                                                                                             
a2enconf mpm_debug.conf; \