redirect log files created in a docker container to stdout / stderr
There are two issues here.
You have an
ENTRYPOINT
defined and you are trying to run a command withCMD
. Docker starts a container with a single process, and when you define both,CMD
is appended toENTRYPOINT
as additional cli args. What the container is running as pid 1 is:/bin/sh -c './testServer 8600 /bin/sh -c "tail $( ls -Art /LOGS | tail -n 1 ) > out_server.log 2>&1"'
Unless testServer runs the extra args, they'll never get used.
If the command you were running did work, it would output everything to /out_server.log inside the container, not to stdout, and it would stop as soon as it reached the end of the input. If that's your pid 1, the container would also exit at that point.
To fix this, you can create an entrypoint.sh to be something like:
#!/bin/sh
./testServer 8600 &
sleep 2 # give testServer time to create the newest log
exec tail -f $( ls -Art /LOGS | tail -n 1 )
That entrypoint starts up testServer in the background and then runs the tail with an exec. The exec replaces pid 1 so that signals are passed through.
Update your Dockerfile to:
FROM ubuntu:16.04
# This apt-get line shouldn't be needed unless something else
# needs the possibly outdated package repo list
# RUN apt-get update
# Removing this volume, you can create it from a docker-compose.yml
# VOLUME ["/LOGS"]
COPY entrypoint.sh testServer /
RUN chmod 755 /entrypoint.sh /testServer
ENTRYPOINT [ "/entrypoint.sh" ]
For more details on why I removed the VOLUME
line, see my blog post here.
Instead you using tail, you can symlink the log file to the container process's stdout. To do so, you need to wrap your executable in a separate script so it gets launched as a process separate from the container's main process.
Script to execute:
#!/bin/bash
# The application log will be redirected to the main docker container process's stdout, so # that it will show up in the container logs
touch /my/app/application.log
ln -sf /proc/1/fd/1 /my/app/application.log
# Execute my app
./testServer 8600
And in the docker file just copy and execute the script
COPY start_server.sh /the/above/script/start_server.sh
CMD ["/bin/bash", "/the/above/script/start_server.sh"]
I found following useful.
#forward request and error logs to docker log collector
RUN ln -sf /dev/stdout /var/log/nginx/access.log \
&& ln -sf /dev/stderr /var/log/nginx/error.log
As a result of above lines, content written to access.log
and error.log
will be written to stdout
and stderr
respectively.
Source