Buat aplikasi Docker menulis ke stdout

49

Saya menggunakan aplikasi pihak ke-3 sesuai dengan saran faktor 12 , dan salah satu poin mengatakan bahwa log aplikasi harus dicetak ke stdout / stderr: maka perangkat lunak pengelompokan dapat mengumpulkannya.

Namun, aplikasi hanya dapat menulis ke file atau syslog. Bagaimana cara mencetak log ini sebagai gantinya?

kolypto
sumber
Mereka sudah pergi ke syslog. Anda bisa mengambilnya dari sana!
Michael Hampton
@MichaelHampton, sepertinya baik-baik saja, tetapi Docker menjalankan satu proses yang dapat menulis ke stdout, dan ini terdengar seperti menggabungkan keduanya?
kolypto
1
Anda dapat memiliki proses daemon menggunakan syslog dan memiliki proses depan yang mencetak?
qkrijger
@qkrijger, poin bagus! Sekarang, apakah ada yang punya pengalaman dengan itu ...?
kolypto

Jawaban:

107

Resep luar biasa diberikan di 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

Sederhananya, aplikasi dapat terus menulis sebagai file, tetapi sebagai hasilnya, barisnya akan masuk ke stdout& stderr!

kolypto
sumber
2
Ini. Aku s. Hanya. Cemerlang. Dan serba guna.
spacediver
11
Satu hal yang menjadi masalah dengan hal ini adalah ketika hal yang Anda jalankan bersikeras untuk mencabut dirinya sendiri ke latar belakang sebagai proses non-root. Saya mengalami ini squid3, dan kemudian mengalami masalah dengan izin /dev/stdout.
mikepurvis
4
Ini tidak selalu berhasil - misalnya jika aplikasi mencoba mencari file, metode ini umumnya tidak akan berfungsi.
mixja
Tautan rusak ...
Babken Vardanyan
4
Semuanya adalah file untuk menang.
RubberDuck
16

Dalam pertanyaan lain, Bunuh proses anak ketika orang tua keluar , saya mendapat respons yang membantu menyelesaikan masalah ini.

Dengan cara ini, kami mengkonfigurasi aplikasi sehingga log ke file, dan terus menerus tail -f. Untungnya, taildapat menerima --pid PID: itu akan keluar ketika proses yang ditentukan keluar. Kami menempatkan di $$sana: PID dari shell saat ini.

Sebagai langkah terakhir, aplikasi yang diluncurkan adalah exec'ed, yang berarti bahwa shell saat ini sepenuhnya diganti dengan aplikasi itu.

Script pelari run.sh,, akan terlihat seperti ini:

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

CATATAN: dengan menggunakan tail -Fkami daftar nama file, dan itu akan membacanya bahkan jika mereka muncul nanti!

Akhirnya, Dockerfile minimalis:

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

Catatan: untuk mengatasi beberapa tail -fperilaku yang sangat aneh (yang mengatakan "telah diganti dengan file jarak jauh. Menyerah pada nama ini") saya mencoba pendekatan lain: semua file log yang dikenal dibuat & dipotong pada saat start up: dengan cara ini saya memastikan mereka ada , dan hanya kemudian - membuntuti mereka:

#! /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
kolypto
sumber
Khusus untuk server Apache saya menggunakan log Pipa ( httpd.apache.org/docs/2.4/logs.html#piped ) dan sepertinya berfungsi.
php-coder
Memecahkan masalah serupa dengan alpine dan tampaknya berfungsi dengan baik pada BusyBox tailtanpa opsi --pid.
Ryan
solusi bekerja untuk saya. sangat berguna, terima kasih.
Tamas Kalman
8

Untuk proses latar belakang dalam wadah buruh pelabuhan, mis. Menghubungkan dengan exec ke / bin / bash yang bisa saya gunakan.

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

Ini mengirimkan output ke stdout dari pid 1, yang merupakan satu buruh pelabuhan naik.

Pieter
sumber
1
Ini jawaban yang benar. Log harus dikirim ke stdout untuk PID1 dan jika aplikasi Anda berjalan di bawah PID lain, itu tidak akan dilihat oleh docker logsatau kubectl logs. Saya punya wadah yang menjadwalkan tugas melalui crontab yang tidak berjalan sebagai PID1.
leeman24
6

untuk nginx Anda dapat nginx.confmenunjuk /dev/stderrdan /dev/stdoutmenyukai ini

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

dan Dockerfileentri Anda seharusnya

/usr/sbin/nginx -g 'daemon off;'
Muayyad Alsadi
sumber
Tidak berfungsi saat proses master tidak berjalan sepertiroot
peedee