プログラムを中心とした個人的なメモ用のブログです。 タイトルは迷走中。
内容の保証はできませんのであしからずご了承ください。

2021/12/24

[Python] Docker コンテナ内のアプリのログをホストの Syslog に追加する

update2022/09/28 event_note2021/12/24 0:22

docker コンテナ内で動作している python アプリのログをホストの syslog に追加します。

Ubuntu 20.04 で作業しましたが、rsyslog は最初からインストールされていました。

概要

Python 標準の logging モジュールに syslog 出力用のハンドラ SysLogHandler があるので、アプリ側ではそれを指定するだけで OK です。

Syslog はホストに対して UDP でログを送信して追加します。
理由は以下です。

  • docker コンテナ内でアプリを動かしているので、今後コンテナが増えたときコンテナごとに rsyslog を設定してやるのが面倒そう
  • 各コンテナのログを一箇所に集約したい
  • syslog の記録には TCP or UDP のポート 514 が使用されるらしいが、SysLogHandler では UDP しか対応していないよう

rsyslog の設定変更

UDP のポート514 でログを待ち受けるように設定を変更します。

/etc/rsyslog.conf を編集します。

$ sudo gedit /etc/rsyslog.conf

以下の2行のコメントを外します。

module(load="imudp")
input(type="imudp" port="514")

変更後は再起動します。

$ sudo systemctl restart rsyslog

アプリ側の実装

ログに関する設定を logging.yaml に切り出しています。

その前提のうえで、以下のように指定するだけでログが UDP で送信されるようになります。

root:
  level: DEBUG
  handlers: [syslog]
handlers:
  syslog:
    class: logging.handlers.SysLogHandler
    formatter: syslog_format
    address: ['host.docker.internal', 514]
    #address: '/dev/log'
    level: INFO
formatters:
  syslog_format:
    format: 'appname: %(module)s %(message)s'

IPアドレスについては、docker コンテナからホストのIPアドレスを参照する必要があるので host.docker.internal を指定します。
(localhost はコンテナ自身を指すので使えない)
ちなみに host.docker.internal はもともと Windows と Mac でしか使えませんでしたが、最近 Linux でも使えるようになったそうです。

これ使えなかったら直接IPアドレスを指定しないといけなくなり、ホストのIPアドレスが変わるたびに修正しないといけなくてマジ困ります。 ってかこれを知るまでずっと困ってました。