Зробіть програму Docker написати на stdout


49

Я розгортаю стороннє додаток відповідно до рекомендацій 12 факторів , і один із пунктів говорить про те, що журнали програм повинні бути надруковані на stdout / stderr: тоді кластерне програмне забезпечення може збирати його.

Однак додаток може записувати лише у файли чи syslog. Як замість цього надрукувати ці журнали?


Вони вже збираються в syslog. Ви можете просто забрати їх звідти!
Майкл Хемптон

@MichaelHampton, здається, добре, але Докер запускає єдиний процес, який може записати в stdout, і це звучить як поєднання двох з них?
колипто

1
Ви можете мати демон-процес використовувати syslog і мати передній процес, який друкує?
qkrijger

@qkrijger, хороший момент! Тепер, якщо хтось має з цим досвід ...?
колипто

Відповіді:


107

Дивовижний рецепт наведено в докерфайлі nginx :

# 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
Це. Є. Просто. Блискуча. І універсальний.
spacediver

11
Єдина річ, яка в цьому полягає в тому, що те, що ви працюєте, наполягає на тому, щоб вивести себе на задній план як позакореневий процес. У мене це є squid3, і в нього виникають проблеми з дозволами /dev/stdout.
mikepurvis

4
Це не завжди працює - наприклад, якщо програма намагається шукати файл, цей метод, як правило, не працює.
мікс

Посилання вниз ...
Бабкен Варданян

4
Все - файл для виграшу.
RubberDuck

16

В іншому запитанні " Убити дочірній процес", коли батько виходить , я отримав відповідь, яка допомогла розібратися в цьому.

Таким чином, ми налаштовуємо додаток таким чином, щоб він реєструвався у файлі та постійно працював у tail -fньому. На щастя, tailможна прийняти --pid PID: він закриється, коли зазначений процес завершиться. Поміщаємо $$туди: PID поточної оболонки.

На завершальному етапі запущена програма exec'ed, що означає, що поточна оболонка повністю замінена на цю програму.

Сценарій Runner,, 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

Вирішує подібні проблеми з альпійською і, здається, працює добре на BusyBox tailбез опції --pid.
Райан

вирішення проблеми працювало на мене. надзвичайно корисно, дякую.
Тамас Кальман

8

Для фонового процесу в докер-контейнері, наприклад, підключення з exec до / bin / bash, яке я зміг використати.

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

Це посилає вихід до stdout pid 1, який є одним докерним підхопленням.


1
Це правильна відповідь. Журнали повинні бути надіслані до stdout для PID1, і якщо ваша програма працює під іншим PID, її не побачать docker logsабо kubectl logs. У мене є контейнер, який планує завдання через crontab, який не працює як PID1.
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,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.