Frage Lassen Sie eine Docker-Anwendung in stdout schreiben


Ich stelle eine Anwendung von Drittanbietern in Übereinstimmung mit der 12-Faktor-Beratung, und einer der Punkte besagt, dass Anwendungsprotokolle zu stdout / stderr gedruckt werden sollten: dann kann Clustering-Software es sammeln.

Die Anwendung kann jedoch nur in Dateien oder Syslog schreiben. Wie drucke ich stattdessen diese Protokolle?


40
2018-05-28 13:32


Ursprung


Sie gehen bereits zu syslog. Sie können sie einfach von dort abholen! - Michael Hampton♦
@MichaelHampton, scheint in Ordnung, aber Docker führt einen einzigen Prozess aus, der auf stdout schreiben kann, und das klingt nach einer Kombination von zwei von ihnen? - kolypto
Sie können einen Daemon Prozess verwenden Syslog und haben einen Front-Prozess, der druckt? - qkrijger
@ qkrijger, guter Punkt! Nun, wenn jemand Erfahrung damit hat ...? - kolypto


Antworten:


Ein erstaunliches Rezept wird in gegeben 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

Einfach, die App kann weiterhin als Datei schreiben, aber als Ergebnis werden die Zeilen zu gehen stdout & stderr!


88
2017-10-07 21:57



Diese. Ist. Gerade. Brillant. Und vielseitig. - spacediver
Die einzige Sache, die ein Problem mit diesem ist, ist, wenn das Ding, das Sie laufen lassen, darauf besteht, sich dem Hintergrund als ein nicht-root-Prozess zuzuwenden. Ich habe das mit squid3und es hat dann Probleme mit Berechtigungen für /dev/stdout. - mikepurvis
Dies funktioniert nicht immer - wenn die Anwendung beispielsweise versucht, die Datei zu suchen, wird diese Methode im Allgemeinen nicht funktionieren. - mixja
Link ist runter ... - Babken Vardanyan
Alles ist eine Datei für den Sieg. - RubberDuck


In einer anderen Frage, Töte den Child-Prozess, wenn der Parent beendet wirdIch habe die Antwort bekommen, die geholfen hat, das zu klären.

Auf diese Weise konfigurieren wir die Anwendung so, dass sie kontinuierlich in einer Datei protokolliert wird tail -f es. Glücklicherweise, tail kann akzeptieren --pid PID: Es wird beendet, wenn der angegebene Prozess beendet wird. Wir stellen $$ dort: PID der aktuellen Shell.

Als letzter Schritt ist die gestartete Anwendung exec'ed, was bedeutet, dass die aktuelle Shell vollständig durch diese Anwendung ersetzt wird.

Runner-Skript, run.sh, wird so aussehen:

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

HINWEIS: durch Verwendung von tail -F Wir listen Dateinamen auf, und es liest sie auch, wenn sie später erscheinen!

Zum Schluss die minimalistische Dockerfile:

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

Hinweis: Einige sehr merkwürdig zu bearbeiten tail -f Verhalten (was sagt "wurde mit einer Remote-Datei ersetzt. Geben Sie diesen Namen auf") Ich versuchte einen anderen Ansatz: alle bekannten Protokolldateien werden beim Start erstellt und abgeschnitten: auf diese Weise stelle ich sicher, dass sie existieren, und nur dann - Tail Sie:

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

14
2018-05-28 19:46



Speziell für Apache Server verwende ich Piped Logs (httpd.apache.org/docs/2.4/logs.html#piped) und sieht so aus, als ob es funktioniert. - php-coder


Für Nginx können Sie haben nginx.conf zeigt auf /dev/stderr und /dev/stdout so was

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

und dein Dockerfile Eintrag sollte sein

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

5
2017-08-01 17:40





Für einen Hintergrundprozess in einem Andock-Container, z. Verbindung mit exec zu / bin / bash konnte ich verwenden.

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

Dies sendet die Ausgabe an die Standardausgabe von pid 1, die der eine Docker-Pickup ist.


0
2017-09-27 06:16