My Dockerfile:
FROM php:7.0-fpm
# Install dependencies, etc
RUN \
&& mkfifo /tmp/stdout \
&& chmod 777 /tmp/stdout
ADD docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
as you can see I'm creating a named pipe at /tmp/stdout
. And my docker-entrypoint.sh
:
#!/usr/bin/env bash
# Some run-time configuration stuff...
exec "./my-app" "$@" | tail -f /tmp/stdout
My PHP application (an executable named my-app
) writes its application logs to /tmp/stdout
. I want those logs to then be captured by Docker so that I can do docker logs <container_id>
and see the logs that the application wrote to /tmp/stdout
. I am attempting to do this by running the my-app
command and then tailing /tmp/stdout
, which will then output the logs to stdout
.
What I'm seeing happen is that when I run my application, it hangs when it writes the first log message. I believe this happens because there is nothing "reading" from the named pipe, and writing to a named pipe blocks until something reads from it. This is confirmed if I do docker exec -it <container_id> bash
, and then do tail -f /tmp/stdout
myself inside the container. Once I do that, the container immediately exits because the application has written its logs to the named pipe.
For reasons that I won't bloat this post with, it's not possible for my-app
itself to write logs to stdout
. It has to use /tmp/stdout
.
Can anybody tell me why this isn't working, and what I need to change? I expect I have to change the exec
call in docker-entrypoint.sh
, but I'm not sure how. Thank you!
What I'm seeing happen is that when I run my application, it hangs when it writes the first log message. I believe this happens because there is nothing "reading" from the named pipe, and writing to a named pipe blocks until something reads from it.
This is correct, see fifo(7)
. But with your example code
exec "./my-app" "$@" | tail -f /tmp/stdout
this should actually work since the pipe will start ./my-app
and tail
simultaneously so that there is something reading from /tmp/stdout
.
But one problem here is that tail -f
will never terminate by itself and so neither your docker-entrypoint.sh
/container. You could fix this with:
tail --pid=$$ -f /tmp/stdout &
exec "./my-app" "$@"
tail --pid
will terminate as soon as the process provided by id terminates where $$
is the pid of the bash
process (and through exec
later the pid of ./my-app
).
For reasons that I won't bloat this post with, it's not possible for
my-app
itself to write logs tostdout
. It has to use/tmp/stdout
.
Does this mean it has to write to a filesystem path or is the path /tmp/stdout
hardcoded?
If you can use any path you can use /dev/stdout
/ /proc/self/fd/1
/ /proc/$$/fd/1
as logging path to let your application write to stdout
.
If /tmp/stdout
is hardcoded try symlinking it to /dev/stdout
:
ln -s /dev/stdout /tmp/stdout