Я развертываю стороннее приложение в соответствии с 12-факторное консультирование, и один из пунктов говорит, что журналы приложений должны быть напечатаны на stdout / stderr: тогда программное обеспечение кластеризации может их собрать.
Однако приложение может писать только в файлы или системный журнал. Как мне вместо этого распечатать эти журналы?
Удивительный рецепт дан в 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
!
Для фонового процесса в контейнере докеров, например подключившись с помощью exec к / bin / bash, я смог использовать.
echo "test log1" >> /proc/1/fd/1
Это отправляет вывод на стандартный вывод pid 1, который принимает докер.
В другом вопросе, Убить дочерний процесс при выходе из родительского, Я получил ответ, который помог разобраться в этом.
Таким образом мы настраиваем приложение так, чтобы оно регистрировалось в файле, и постоянно tail -f
Это. К счастью, tail
могу принять --pid PID
: он выйдет, когда завершится указанный процесс. Ставим $$
там: PID текущей оболочки.
На последнем этапе запущенное приложение exec
'ed, что означает, что текущая оболочка полностью заменяется этим приложением.
Сценарий бегуна, 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
для 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;'