34

I'm building a docker image for a Symfony application. In this image, I want to stream the Symfony logs to stdout. So, similar to how nginx logs are configured, I added this line to my Dockerfile:

ln -sf /dev/stdout /var/www/project/app/logs/prod.log

Inside the container, I can see this:

$ ls /var/www/project/app/logs/ -l
total 12
-rw-r--r-- 1 501 games 4473 Jul 21 08:36 dev.log
lrwxrwxrwx 1 501 games   11 Jul 21 08:35 prod.log -> /dev/stdout

However, the app throws following error:

PHP Fatal error: Uncaught exception 'UnexpectedValueException' with message 'The stream or file "/var/www/project/app/logs/prod.log" could not be opened: failed to open stream: No such file or directory' in /var/www/project/app/cache/prod/classes.php:5808
Stack trace:
#0 /var/www/project/app/cache/prod/classes.php(5746): Monolog\Handler\StreamHandler->write(Array)
#1 /var/www/project/app/cache/prod/classes.php(5917): Monolog\Handler\AbstractProcessingHandler->handle(Array)
#2 /var/www/project/app/cache/prod/classes.php(6207): Monolog\Handler\FingersCrossedHandler->handle(Array)
#3 /var/www/project/app/cache/prod/classes.php(6276): Monolog\Logger->addRecord(500, 'Fatal Error: Un...', Array)
#4 /var/www/project/app/cache/prod/classes.php(1978): Monolog\Logger->log('critical', 'Fatal Error: Un...', Array)
#5 /var/www/project/app/cache/prod/classes.php(2034): Symfony\Component\Debug\ErrorHandler->handleException(Object(Symfony\Component\Debug\Exception\FatalErrorException), Array)
#6 [internal function]: Symfony\Component\Debug\E in /var/www/project/app/cache/prod/classes.php on line 5808

Any suggestions ?

A.L
  • 10,259
  • 10
  • 67
  • 98
Webberig
  • 2,746
  • 1
  • 23
  • 19
  • 4
    The message lets no room for speculation: The stream or file "/var/www/project/app/logs/prod.log" could not be opened: failed to open stream: No such file or directory – Honk der Hase Jul 21 '16 at 09:13
  • Obviously... It doesn't seem to be capable of opening the file for writing since it's a symbolic link pointing to /dev/stdout. But how could I achieve this ? (aka make Symfony log to stdout instead of this file) – Webberig Jul 21 '16 at 09:18
  • how is the file opened? ie. only using "w" flag? – Honk der Hase Jul 21 '16 at 09:24
  • Symfony uses Monolog for logging, and I'm using the default configuration. I have no idea how Monolog treats file IO... – Webberig Jul 21 '16 at 09:39
  • Maybe that helps: http://symfony.com/doc/current/cookbook/logging/monolog_console.html – Honk der Hase Jul 21 '16 at 09:53

1 Answers1

67

With the help of Monolog, it is very easy to send logs to stdout/stderr. My examples are using stderr, but I think it's the same with stdout.

Instead of defining a log file you just enter the preferred stream path

path:  "php://stderr"

BUT you are not done yet. You also have to configure PHP accordingly. The workers have to catch the output of their processes and log this output again to their stderr.

PHP Configuration

#/etc/php/7.0/fpm/php-fpm.conf
error_log = /proc/self/fd/2

#/etc/php/7.0/fpm/pool.d/www.conf
catch_workers_output = yes

Symfony Configuration

# app/config/config_prod.yml
monolog:
    handlers:
        main:
            type:         fingers_crossed
            action_level: error
            handler:      nested
        nested:
            type:  stream
            path:  "php://stderr"
            level: debug
        console:
            type:  console

If you are using any process control system in a fat docker container you have to make sure that this system also logs to stdout (or stderr).

Example with supervisor:

[supervisord]
nodaemon=true
;@see http://blog.turret.io/basic-supervisor-logging-with-docker/
;we need the output from the controlled processes
;but this is only possible with lowered loglevel
loglevel=debug

All in all make sure that:

  • The application logs to stdout/stderr
  • PHP catches workers output and logs to stderr
  • optional: any process control system has to forward output of managed processes to stdout/stderr
Community
  • 1
  • 1
frastel
  • 686
  • 6
  • 3
  • 2
    What if you want Symfony to log to both `var/logs/*.log` and `stderr`? Probably duplicate handlers are needed since there doesn't seem to be any multicast support. – Teoh Han Hui Feb 23 '17 at 04:41
  • 10
    You don't need to change any php-fpm settings if you're using the standard Docker image, it includes the stated configuration settings for you. – Anton Babushkin Aug 28 '17 at 01:47
  • 2
    @TeohHanHui in general I would avoid using log files with docker and always use output. You can mark your output with instance info ( if you need specifics ) and stream them to one place ( where you can filter it by instance if you need ). Docker images are normally running on limited memory and risk of hard drive space running out is pretty big. Also, debugging stuff when you don't aggregate logs is next to impossible. – Maciej Paprocki Sep 17 '20 at 13:38
  • For Symfony 5.x you'd put the configuration in `config/packages/prod/monolog.yaml` instead of `app/config/config_prod.yml` – chiborg Oct 24 '20 at 12:46
  • but this is using stderr, datadog for example would consider all these logs as errors, how to use stdout instead of stderr ? – Dany Y Dec 07 '20 at 19:23