<p>I've seen in a lot of docker containers that it's a common practice to create a log file and log like this </p>

<pre><code>/var/log/container.log
...

tail  -f /var/log/container.log
</code></pre>

<p>And somehow the output seems to be taken by the container runtime log driver. So if I run</p>

<pre><code>docker container logs container
</code></pre>

<p>This will show the output of the file <code>container.log</code></p>

<p>I know the best practice for any container is to log on <code>stdout</code> and <code>stderr</code>, but I can't understand why the first option works (create a file and run tail on it). Is it because the output of the <code>tail</code> is taken by the driver log and it merges it with the contents of stdout? </p>

<p>Really appreciate your help.
Thanks.</p>

Ivan Hernandez
<p>The <code>tail -f</code> approach isn't really a best practice.</p>

<p>As you note, the right way to run a process and produce logs is to have it write its output directly to stdout and stderr, and <code>docker logs</code> will capture them.  You can configure Docker's logging layer to send them somewhere else; if you move to a clustered infrastructure like Kubernetes, you can configure its logging layer to capture logs as well, without modifying your application code.</p>

<pre class="lang-sh prettyprint-override"><code>#!/bin/sh
# I am the script that runs the main container process.
# Run a single process, as a foreground process; when that
# process ends, the container exits.
exec some_server --no-daemon --log-file /dev/stdout
</code></pre>

<p>When you see <code>tail -f</code> it generally looks like this:</p>

<pre class="lang-sh prettyprint-override"><code>#!/bin/sh
# Start something as a background process.
something --log-file /var/log/something.log &amp;
# Hackily keep the container from exiting.
tail -f /var/log/something.log
</code></pre>

<p>The main container process is the <code>tail</code> process.  When <code>tail</code> exits, the container will stop, and if you <code>docker stop</code> the container, the signal will go to <code>tail</code>.  Oh, by the way, as a side effect, there's a <code>something</code> process running, but if it fails Docker has no way of noticing it.  Still, since the <code>tail</code> process is the main process and <code>tail -f</code> will never exit, this keeps a container running, and it will make its file-based logs visible to the container's stdout.</p>

<p>Another interesting approach here is what the Docker Hub <code>httpd</code> image does: it sets its logging to point at a file, but the default content of that file is a symlink to <code>/dev/stdout</code>.</p>

<pre class="lang-sh prettyprint-override"><code>RUN mkdir /var/log/something \
 &amp;&amp; ln -s /dev/stdout /var/log/something/something.log
CMD ["something", "--log-file", "/var/log/something/something.log"]
</code></pre>

<p>This is interesting because the default behavior will be to write things to that log file, but it's really the <code>/dev/stdout</code> special device, so it will go to the process's stdout (of the main container process).  If you want to capture this in a file instead, you can bind-mount your own directory over <code>/var/log/something</code> which will hind the symlink.</p>
