Dockerアプリケーションに標準出力への書き込みを行わせます


49

12ファクターアドバイザリに準拠してサードパーティアプリケーションを展開していますが、ポイントの1つは、アプリケーションログをstdout / stderrに出力する必要があることを示しています。その後、クラスタリングソフトウェアがそれを収集できます。

ただし、アプリケーションはファイルまたはsyslogにのみ書き込むことができます。代わりにこれらのログを印刷するにはどうすればよいですか?


彼らはすでにsyslogにアクセスしています。そこから拾うことができます!
マイケルハンプトン

@MichaelHamptonは問題ないようですが、Dockerはstdoutに書き込むことができる単一のプロセスを実行します。これは、2つを組み合わせたように聞こえますか?
kolypto

1
デーモンプロセスにsyslogを使用させ、フロントプロセスに印刷させることができますか?
qkrijger

@qkrijger、良い点!さて、もし誰かがそれを経験していたら...?
kolypto

回答:


107

驚くべきレシピがnginx Dockerfileで提供されています:

# 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

単純に、アプリはファイルとしてファイルへの書き込みを続けることができますが、その結果、行はstdout&に移動しstderrます!


2
この。です ただ。ブリリアント。汎用性があります。
スペースダイバー14年

11
これに関する問題の1つは、実行しているものが非ルートプロセスとしてバックグラウンドに自分自身をフォークすることを主張する場合です。私はこれを持っていますsquid3、そしてそれは上のアクセス許可に問題があり/dev/stdoutます。
mikepurvis 14

4
これは常に機能するとは限りません。たとえば、アプリケーションがファイルをシークしようとすると、この方法は通常機能しません。
mixja

リンクが...ダウンしている
Babken Vardanyan

4
すべてが勝利のためのファイルです。
ラバーダック

16

別の質問で、親が終了したときに子プロセスを強制終了し、これを整理するのに役立つ応答を得ました。

このようにして、ファイルにログを記録し、継続的tail -fに記録するようにアプリケーションを構成します。幸いなことに、tail受け入れることができます--pid PID:指定されたプロセスが終了すると終了します。$$そこに置きます:現在のシェルのPID。

最後のステップとして、起動されたアプリケーションがexec削除されます。つまり、現在のシェルがそのアプリケーションに完全に置き換えられます。

ランナースクリプト、run.shは次のようになります。

#! /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

注:を使用tail -Fすると、ファイル名がリストされ、後で表示されてもファイル名が読み取られます!

最後に、最小限のDockerfile:

FROM ubuntu
ADD run.sh /root/run.sh
CMD ['/root/run.sh']

注:いくつかの非常に奇妙なtail -f動作(「リモートファイルに置き換えられました。この名前を放棄します」と言います)を動作させるために、別の方法を試しました:既知のログファイルはすべて作成され、起動時に切り捨てられます。 、そしてその時だけ-それらを尾:

#! /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

特にApacheサーバーでは、Pipedログ(httpd.apache.org/docs/2.4/logs.html#piped)を使用しており、動作しているように見えます。
php-coder

アルパインの同様の問題を解決しtail、--pidオプションなしでBusyBoxで正常に動作するようです。
ライアン

回避策は私のために働いた。非常に便利です、ありがとう。
タマスカルマン

8

Dockerコンテナのバックグラウンドプロセス、たとえばexecを使用して/ bin / bashに接続するには、使用できました。

echo "test log1" >> /proc/1/fd/1

これにより、出力がpid 1のstdoutに送信されます。これは、1つのdockerピックアップです。


1
これは正解です。ログはPID1のstdoutに送信される必要があり、アプリケーションが別のPIDで実行されている場合、docker logsまたはによって表示されませんkubectl logs。PID1として実行されていないcrontabを介してタスクをスケジュールするコンテナーがあります。
leeman24

6

nginxのためにあなたがしていることができますnginx.confを指している/dev/stderr/dev/stdout、このように

user  nginx;
worker_processes  4;
error_log  /dev/stderr;
http {
    access_log  /dev/stdout  main;
...

あなたのDockerfileエントリーは

/usr/sbin/nginx -g 'daemon off;'

マスタープロセスが次のように実行されていない場合は機能しませんroot
peedee
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.