概要
Dockerのログをrsyslogで出力する方法。
関連
環境
- CentOS 7.7
- rsyslog 8.24.0-41.el7_7.2
Dockerの設定
Dockerもしくはdocker-composeで、以下のパラメータを指定し、rsyslogにログが渡るようにする。
ログには、This is a example.という文字列が出力されるようにする。
| 設定内容 | Docker | docker-compose |
|---|---|---|
| syslogを使う | --log-driver=syslog | logging.driver |
| ログの種類の分類 | --log-opt syslog-facility={facility名} | logging.options.syslog-facility |
| ログやファイル名に使用する名前 | --log-opt tag={任意の文字列} | logging.options.tag |
dockerコマンドの場合
$ sudo docker run --rm \
--name sample-container \
--log-driver=syslog \
--log-opt syslog-facility=daemon \
--log-opt tag=sample-app/{{.Name}}/{{.ID}} \
-it ${Dockerイメージ名} \
/bin/bash -c 'echo "This is a example."'
docker-composeの場合
version: '3'
services:
sample-container:
image: sample-image
command: 'echo "This is a example."'
logging:
driver: syslog
options:
syslog-facility: daemon
tag: sample-app/{{.Name}}/{{.ID}}
| 変数 | 意味 |
|---|---|
| {{.Name}} | コンテナ名 |
| {{.ID}} | コンテナID |
rsyslogの設定
rsyslogのtemplateという機能を使って、ログファイル名の指定をする。
/var/log/docker/sample-app_年月日.logというログファイル名になるようにする。
/etc/rsyslog.d/10-docker.conf
$template DockerLogs, "/var/log/docker/%programname%_%$year%%$month%%$day%.log"
if $syslogfacility-text == 'daemon' and $programname contains 'sample-app' then -?DockerLogs
& stop
| 変数 | 意味 |
|---|---|
| $template | templateを使うための宣言 |
| DockerLogs | template名。任意の文字列でOK |
| %programname% | ログを出力しているプログラム名 |
| $programname | ログを出力しているプログラム名 |
| $syslogfacility-text | --log-opt syslog-facility もしくは logging.options.syslog-facility に指定した文字列 |
その他の変数は以下を参照
rsyslog.confの文法
if $syslogfacility-text == 'daemon' and $programname contains 'sample-app' then -?DockerLogs
$syslogfacility-textがdaemonで、$programnameにsample-appという文字列が含まれるときのみログを出す。
$syslogfacility-textは--log-opt syslog-facility もしくは logging.options.syslog-facilityと、$programnameは--log-opt tag もしくは logging.options.tag と合わせる必要がある。
rsyslogのrestart
/etc/rsyslog.d/10-docker.confを変更したあとはrestartが必要。
$ sudo systemctl restart rsyslog
出力されるログ
Dockerもしくはdocker-composeを実行。
実際に出力されるログ。
-
Format:
/var/log/docker/{%programname%}_{%$year%%$month%%$day%}.log -
e.g.):
/var/log/docker/sample-app_20200218.log
sample-app/{コンテナ名}/{コンテナID}の部分は、--log-opt tag もしくは logging.options.tag に指定した文字列。
Feb 18 17:03:19 example-hostname sample-app/sample-container/{コンテナID}[{dockerdのプロセスID}]: This is a example.
コンテナIDのみを抽出してログファイル名にする
nomatch-Modeを使って、文字列を抽出してファイル名に使用する方法。
この方法を利用して、コンテナIDのみをログファイル名にしてみる。
rsyslogの設定
/etc/rsyslog.d/10-docker.confに以下のように設定する。
$template DockerLogs, "/var/log/docker/%syslogtag:R,ERE,1,FIELD:sample-app/sample-container/(.*)\[(.*)\]:--end%.log"
if $syslogfacility-text == 'daemon' and $programname contains 'sample-app' then -?DockerLogs
& stop
"/var/log/docker/%syslogtag:R,ERE,1,FIELD:sample-app/sample-container/(.*)\[(.*)\]:--end%.log"の部分の説明。
| 変数 | 意味 |
|---|---|
| /var/log/docker/ | ログファイルを出力する場所 |
| %syslogtag% | --log-opt tag もしくは logging.options.tag に指定した文字列。正規表現で抽出する対象文字列となる。 |
| R | nomatchを利用するときはここはR |
| ERE | 正規表現のタイプ。BRE of ERE。EREはBREを拡張したモード。通常こちらを選択する。 |
| 1 | submatchの番号 |
| FIELD | nomatchモードの指定。枠下参照。 |
sample-app/sample-container/(.*)\[(.*)\]: |
「R」の前の文字列(この場合は%syslogtag%)からこの正規表現で文字列を抽出し、ファイル名に使用する |
| --end%.log | 最後に必ず書く |
今回の設定の場合は、%syslogtag%から正規表現sample-app/sample-container/(.*)\[(.*)\]:で抽出した文字列をファイル名として使用するということになる。
nomatchモードについて
正規表現でマッチするものがなかった場合に返す、デフォルトの文字列をModeによって指定する。
各Modeごとに返す文字列は以下のようになっているが、FIELDを指定した場合は、正規表現対象の文字列全てが返される。(この場合は%syslogtag%)
| Mode | Returned |
|---|---|
| DFLT | "**NO MATCH**" |
| BLANK | "" (empty string) |
| ZERO | "0" |
| FIELD | full content of original field |
引用元:Property Replacer nomatch mode
今回のFIELDの正規表現の場合の挙動
%syslogtag% = sample-app/sample-container/f76f6af73829[27081]
から、以下の正規表現で抽出をする。
sample-app/sample-container/(.*)\[(.*)\]:
submatchは1を指定しているため、1つ目の(.*)のみが抽出される。
つまり、コンテナIDであるf76f6af73829が抽出される。
結果、以下がファイル名となる。
/var/log/docker/f76f6af73829.log
rsyslogのrestart
/etc/rsyslog.d/10-docker.confを変更したあとはrestartが必要。
$ sudo systemctl restart rsyslog
出力されるログ
Dockerもしくはdocker-composeを実行。
この設定で実際に出力されるログ。
-
Format:
/var/log/docker/sample-app/{コンテナ名}/{コンテナID}.log -
e.g.):
/var/log/docker/f76f6af73829.log
sample-app/{コンテナ名}/{コンテナID}の部分は、--log-opt tag もしくは logging.options.tag に指定した文字列。
Feb 18 17:21:23 example-hostname sample-app/sample-container/f76f6af73829[27081]: This is a example.
正規表現にマッチしない場合
rsyslogの設定
/etc/rsyslog.d/10-docker.confの正規表現の一部を、sample-app_nomatchとしてマッチしないようにしてみる。
$template DockerLogs, "/var/log/docker/%syslogtag:R,ERE,1,FIELD:sample-app_nomatch/sample-container/(.*)\[(.*)\]:--end%.log"
if $syslogfacility-text == 'daemon' and $programname contains 'sample-app' then -?DockerLogs
& stop
rsyslogのrestart
/etc/rsyslog.d/10-docker.confを変更したあとはrestartが必要。
$ sudo systemctl restart rsyslog
出力されるログ
Dockerもしくはdocker-composeを実行。
この設定で実際に出力されるログ。
-
Format:
/var/log/docker/sample-app/{コンテナ名}/{コンテナID}[{dockerdのプロセスID}].log -
e.g.):
/var/log/docker/sample-app/sample-container/de64dadc7e97\[27081\]\:.log
sample-app/{コンテナ名}/{コンテナID}の部分は、--log-opt tag もしくは logging.options.tag に指定した文字列。
Feb 18 17:21:23 example-hostname sample-app/sample-container/de64dadc7e97[27081]: This is a example
正規表現がマッチせず、FIELDをしているので、%syslogtag%の中身がそのままファイル名となる。
前述したように、DFLTの場合はファイル名が**NO MATCH**.log、ZEROの場合は0.logがファイル名となる。BLANKの場合はログファイルが出力されない。