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:
#! /usr/bin/env bash
set -eu
rm -rf /var/log/my-application.log
tail --pid $$ -F /var/log/my-application.log &
exec /path/to/my-application --logfile /var/log/my-application.log
NOTE: by using tail -F
we list filenames, and it will read them even if they appear later!
Finally, the minimalistic Dockerfile:
FROM ubuntu
ADD run.sh /root/run.sh
CMD ['/root/run.sh']
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:
#! /usr/bin/env bash
set -eu
LOGS=/var/log/myapp/
( umask 0 && truncate -s0 $LOGS/http.{access,error}.log )
tail --pid $$ -n0 -F $LOGS/* &
exec /usr/sbin/apache2 -DFOREGROUND