CUBE SUGAR CONTAINER

技術系のこと書きます。

Docker コンテナのログを syslog でリモートホストに飛ばす

今回は Docker コンテナのログを syslog で別のホストに飛ばしてみることにする。 言うまでもなく、ロギングはシステムを運用する上で欠かせない要素の一つ。

Docker には、あらかじめ複数のロギングドライバが組み込まれていて、それらを使い分けることができる。 今回使うのはその中の一つで syslog ドライバという名前がついている。 このドライバで飛ばした Docker コンテナのログを syslog-ng で受け取ってファイルに書き出してみよう。 ただし、リモートホストといっても TCP 越しにログを飛ばすだけで単一のホスト上で組んでしまうことにする。

ロギングドライバについての詳細はこのドキュメントに記載されている。

docs.docker.com

syslog ドライバに限った話についてはこちらに書いてある。

docs.docker.com

使った環境は次の通り。

$ cat /etc/redhat-release 
CentOS Linux release 7.4.1708 (Core) 
$ uname -r
3.10.0-693.17.1.el7.x86_64
$ sudo docker version
Client:
 Version:         1.12.6
 API version:     1.24
 Package version: docker-1.12.6-71.git3e8e77d.el7.centos.1.x86_64
 Go version:      go1.8.3
 Git commit:      3e8e77d/1.12.6
 Built:           Tue Jan 30 09:17:00 2018
 OS/Arch:         linux/amd64

Server:
 Version:         1.12.6
 API version:     1.24
 Package version: docker-1.12.6-71.git3e8e77d.el7.centos.1.x86_64
 Go version:      go1.8.3
 Git commit:      3e8e77d/1.12.6
 Built:           Tue Jan 30 09:17:00 2018
 OS/Arch:         linux/amd64

syslog-ng をインストールする

まずはログを受ける syslog-ng をインストールする。 CentOS 7 の場合は EPEL を入れると yum でインストールできるようになる。

$ sudo yum -y install epel-release
$ sudo yum -y install syslog-ng

続いて syslog-ng の設定ファイルを用意する。 ここでは TCP/514 番ポートで受けた syslog を /var/log/docker/docker.log に書き出すように設定している。

$ cat << 'EOF' | sudo tee /etc/syslog-ng/conf.d/docker.conf > /dev/null
source s_remote_tcp {
  tcp(ip(0.0.0.0), port(514));
};

destination d_docker {
  file("/var/log/docker/docker.log");
};

log {
  source(s_remote_tcp);
  destination(d_docker);
};
EOF

設定ファイルに不備がないかをチェックしておこう。 以下のコマンドで出力が何も返ってこなければ問題ない。 もし設定ファイルの書式を間違えていると、その箇所を教えてくれる。

$ sudo syslog-ng -s

続いて、ログを書き出す先のディレクトリを作っておこう。

$ sudo mkdir -p /var/log/docker

これでログを受ける準備が整ったので syslog-ng のサービスを起動する。

$ sudo systemctl enable syslog-ng
$ sudo systemctl start syslog-ng

ちゃんと設定通り TCP/514 番ポートで Listen していることが見て取れる。

$ sudo ss -tlnp | grep 514
LISTEN     0      128          *:514                      *:*                   users:(("syslog-ng",pid=3438,fd=8))

Docker をインストールする

続いて Docker をインストールする。 Docker は標準リポジトリからでもインストールできる。 ちょっとバージョンが古いけどね。

$ sudo yum -y install docker

インストールできたら Docker のサービスを起動する。

$ sudo systemctl enable docker
$ sudo systemctl start docker

Docker コンテナのログを syslog で飛ばす

あとはDocker コンテナの起動時にドライバとそのオプションを設定するだけ。 以下のように --log-driver オプションに syslog を指定すると syslog ドライバを使うようになる。 さらに --log-opt オプションで syslog-address を指定すると目当てのプロトコルとポートにログを送れる。

$ sudo docker run \
  --log-driver=syslog \
  --log-opt syslog-address=tcp://localhost:514 \
  -it alpine \
  ls /

syslog-ng の出力先のファイルを確認すると、ちゃんと実行結果がログとして残されていることが分かる。

$ sudo cat /var/log/docker/docker.log 
Feb 13 13:41:53 127.0.0.1 docker/f825d108f7fa[3590]: bin    etc    lib    mnt    root   sbin   sys    usr
Feb 13 13:41:53 127.0.0.1 docker/f825d108f7fa[3590]: dev    home   media  proc   run    srv    tmp    var

念のため、もうちょっとログの量が多い場合も試しておこう。 以下では MySQL のコンテナを起動している。

$ sudo docker run \
  --log-driver=syslog \
  --log-opt syslog-address=tcp://localhost:514 \
  -e MYSQL_ROOT_PASSWORD=rootpasswd \
  -it mysql

syslog-ng の出力先を確認すると、ちゃんと MySQL のログが出力されていることが分かる。

$ sudo tail /var/log/docker/docker.log 
Feb 13 13:45:18 127.0.0.1 docker/6b6389751769[3590]: 2018-02-13T13:45:18.041553Z 0 [Warning] 'user' entry 'mysql.session@localhost' ignored in --skip-name-resolve mode.
Feb 13 13:45:18 127.0.0.1 docker/6b6389751769[3590]: 2018-02-13T13:45:18.041564Z 0 [Warning] 'user' entry 'mysql.sys@localhost' ignored in --skip-name-resolve mode.
Feb 13 13:45:18 127.0.0.1 docker/6b6389751769[3590]: 2018-02-13T13:45:18.041597Z 0 [Warning] 'db' entry 'performance_schema mysql.session@localhost' ignored in --skip-name-resolve mode.
Feb 13 13:45:18 127.0.0.1 docker/6b6389751769[3590]: 2018-02-13T13:45:18.041606Z 0 [Warning] 'db' entry 'sys mysql.sys@localhost' ignored in --skip-name-resolve mode.
Feb 13 13:45:18 127.0.0.1 docker/6b6389751769[3590]: 2018-02-13T13:45:18.041622Z 0 [Warning] 'proxies_priv' entry '@ root@localhost' ignored in --skip-name-resolve mode.
Feb 13 13:45:18 127.0.0.1 docker/6b6389751769[3590]: 2018-02-13T13:45:18.043787Z 0 [Warning] 'tables_priv' entry 'user mysql.session@localhost' ignored in --skip-name-resolve mode.
Feb 13 13:45:18 127.0.0.1 docker/6b6389751769[3590]: 2018-02-13T13:45:18.043806Z 0 [Warning] 'tables_priv' entry 'sys_config mysql.sys@localhost' ignored in --skip-name-resolve mode.
Feb 13 13:45:18 127.0.0.1 docker/6b6389751769[3590]: 2018-02-13T13:45:18.054543Z 0 [Note] Event Scheduler: Loaded 0 events
Feb 13 13:45:18 127.0.0.1 docker/6b6389751769[3590]: 2018-02-13T13:45:18.054868Z 0 [Note] mysqld: ready for connections.
Feb 13 13:45:18 127.0.0.1 docker/6b6389751769[3590]: Version: '5.7.21'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)

ばっちり。

めでたしめでたし。