Je déploie une application tierce conformément à la 12 factor Advisory , et l'un des points indique que les journaux d'application doivent être imprimés sur stdout/stderr: le logiciel de clustering peut alors le collecter.
Cependant, l'application ne peut écrire que dans des fichiers ou syslog. Comment imprimer ces journaux à la place?
Une recette étonnante est donnée dans le 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
Simplement, l'application peut continuer à y écrire sous forme de fichier, mais en conséquence, les lignes iront à stdout
& stderr
!
Dans une autre question, Tuer le processus enfant lorsque le parent quitte , j'ai obtenu la réponse qui a aidé à trier cela.
De cette façon, nous configurons l'application pour qu'elle se connecte à un fichier et en continu tail -f
il. Heureusement, tail
peut accepter --pid PID
: il se fermera à la fin du processus spécifié. Nous mettons $$
there: PID du shell actuel.
Comme dernière étape, l'application lancée est exec
'ed, ce qui signifie que le shell actuel est complètement remplacé par cette application.
Script du coureur, run.sh
, ressemblera à ceci:
#! /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
REMARQUE: en utilisant tail -F
nous listons les noms de fichiers, et il les lira même s'ils apparaissent plus tard!
Enfin, le Dockerfile minimaliste:
FROM ubuntu
ADD run.sh /root/run.sh
CMD ['/root/run.sh']
Remarque: pour travailler quelques-uns extrêmement étranges tail -f
comportement (qui dit "a été remplacé par un fichier distant. abandonner ce nom") j'ai essayé une autre approche: tous les fichiers journaux connus sont créés et tronqués au démarrage: de cette façon, je m'assure qu'ils existent, et alors seulement - - les queue:
#! /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
Pour un processus d'arrière-plan dans un conteneur Docker, par ex. connexion avec exec à/bin/bash que j'ai pu utiliser.
echo "test log1" >> /proc/1/fd/1
Cela envoie la sortie à la sortie standard du pid 1, qui est le seul pick-up Docker.
pour nginx, vous pouvez avoir nginx.conf
pointant vers /dev/stderr
et /dev/stdout
comme ça
user nginx;
worker_processes 4;
error_log /dev/stderr;
http {
access_log /dev/stdout main;
...
et votre Dockerfile
entrée doit être
/usr/sbin/nginx -g 'daemon off;'