I'm deploying a 3rd-party application in compliance with the 12 factor advisory, and one of the points tell that application logs should be printed to stdout/stderr: then clustering software can collect it.
However, the application can only write to files or syslog. How do I print these logs instead?
An amazing recipe is given in the nginx Dockerfile:
Simply, the app can continue writing to it as a file, but as a result the lines will go to
stdout
&stderr
!For a background process in a docker container, e.g. connecting with exec to /bin/bash I was able to use.
This sends the output to the stdout of pid 1, which is the one docker pick's up and logs.
In another question, Kill child process when the parent exits, I got the response that helped to sort this out.
This way, we configure the application so it logs to a file, and continuously
tail -f
it. Luckily,tail
can accept--pid PID
: it will exit when the specified process exits. We put$$
there: PID of the current shell.As a final step, the launched application is
exec
'ed, which means that the current shell is completely replaced with that application.Runner script,
run.sh
, will look like this:NOTE: by using
tail -F
we list filenames, and it will read them even if they appear later!Finally, the minimalistic Dockerfile:
Note: to workaroung some extremely strange
tail -f
behavior (which says "has been replaced with a remote file. giving up on this name") i tried another approach: all known log files are created & truncated on start up: this way I ensure they exist, and only then -- tail them:for nginx you can have
nginx.conf
pointing to/dev/stderr
and/dev/stdout
like thisand your
Dockerfile
entry should beIn my case making a symbolic link to stdout didn't work so instead I run the following command
I've just had to solve this problem with apache2, and wrestled with using CustomLog to try redirecting to
/proc/1/fd/1
but couldn't get that working. In my implementation, apache was not running aspid 1
, so kolypto's answer didn't work as is. Pieter's approach seemed compelling, so I merged the two and the result works wonderfully:Technically this keeps the apache
access.log
anderror.log
going tostdout
andstderr
as far as the docker log collector is concerned, but it'd be great if there were a way to separate the two outside the container, like a switch fordocker logs
that would show only one or the other...