zaki work log

作業ログやら生活ログやらなんやら

[Docker]コンテナ実行時にlog-optsでログサイズ上限とローテート数を設定してホストのストレージが溢れないようにする

コンテナのお作法として、アプリのログはstdoutへ出力することで、Dockerのロギング機能に任せることができる。
ただし、Dockerのデフォルトだとサイズ制限は無いので、上限設定を行っていないとホストのストレージを使い切ってしまうので注意。

逆に言うと、アプリのログはDockerにまかせることで、サイズ上限やローテートもやってくれるので、ログローテートの仕組みを別途用意する必要はない。

※ CPUとメモリについてはこちら。

zaki-hmkc.hatenablog.com

確認用Dockerイメージ作成

#!/bin/bash

echo "container started..."

while true;
do
    echo "$(date +'%Y-%m-%d %H-%M-%S'): $(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c 64)"
    usleep 100000
done
FROM centos:7

RUN yum install -y initscripts && \
    yum clean all
COPY createlog.sh /createlog.sh

CMD ["/createlog.sh"]
$ sudo docker build -t log-sample .
$ sudo docker images log-sample
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
log-sample          latest              b4ec88d926dc        31 seconds ago      203MB

(補足) スクリプト解説

cat /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c 64は、ランダムな[a-zA-Z0-9]の文字を64バイトだけ出力。
あとusleepはmicrosecondsでsleepするコマンド。centos:7イメージにはデフォルトで入ってなかったのでyumで追加している。
sleepを入れているのは負荷があがりすぎないようにするためと、停止のシグナルをキャッチしやすくするため。

docker run オプション

ログサイズ制限ありで実行

設定するのは以下。

      --log-opt list                   Log driver options

optionsの内訳は--helpだと確認できないのでドキュメント確認。

docs.docker.com

実はここを見てもよくわからない。
というのも--log-optオプションは--log-driverに指定するログドライバによって設定できるオプションが変わるため。
今回はデフォルトのjson-fileについて。
json-file--log-driverはこちら。

docs.docker.com

ログファイルのサイズを制限するのはこれ。

max-size

今回は制限がかかることを見るだけなので、100KBとする。

$ sudo docker run -d --rm --log-opt max-size=100k log-sample
a7fe3ed543c26bac2f50a93f4ef5a068fffe26ec0523872d23552c64b0b4705a

ログファイルの出力先を確認

$ sudo docker inspect a7f | grep LogPath
        "LogPath": "/var/lib/docker/containers/a7fe3ed543c26bac2f50a93f4ef5a068fffe26ec0523872d23552c64b0b4705a/a7fe3ed543c26bac2f50a93f4ef5a068fffe26ec0523872d23552c64b0b4705a-json.log",

ログファイルのサイズを確認する

$ ls -lh /var/lib/docker/containers/a7fe3ed543c26bac2f50a93f4ef5a068fffe26ec0523872d23552c64b0b4705a/a7fe3ed543c26bac2f50a93f4ef5a068fffe26ec0523872d23552c64b0b4705a-json.log
[zaki@example ~]$ sudo ls -lh /var/lib/docker/containers/a7fe3ed543c26bac2f50a93f4ef5a068fffe26ec0523872d23552c64b0b4705a/
合計 152K
-rw-r-----. 1 root root  98K  9月  9 20:26 a7fe3ed543c26bac2f50a93f4ef5a068fffe26ec0523872d23552c64b0b4705a-json.log
drwx------. 2 root root    6  9月  9 20:24 checkpoints
-rw-------. 1 root root 2.9K  9月  9 20:24 config.v2.json
-rw-r--r--. 1 root root 1.5K  9月  9 20:24 hostconfig.json
-rw-r--r--. 1 root root   13  9月  9 20:24 hostname
-rw-r--r--. 1 root root  174  9月  9 20:24 hosts
drwx------. 2 root root    6  9月  9 20:24 mounts
-rw-r--r--. 1 root root   66  9月  9 20:24 resolv.conf
-rw-r--r--. 1 root root   71  9月  9 20:24 resolv.conf.hash
[zaki@example ~]$ sudo ls -lh /var/lib/docker/containers/a7fe3ed543c26bac2f50a93f4ef5a068fffe26ec0523872d23552c64b0b4705a/
合計 28K
-rw-r-----. 1 root root  780  9月  9 20:26 a7fe3ed543c26bac2f50a93f4ef5a068fffe26ec0523872d23552c64b0b4705a-json.log
drwx------. 2 root root    6  9月  9 20:24 checkpoints
-rw-------. 1 root root 2.9K  9月  9 20:24 config.v2.json
-rw-r--r--. 1 root root 1.5K  9月  9 20:24 hostconfig.json
-rw-r--r--. 1 root root   13  9月  9 20:24 hostname
-rw-r--r--. 1 root root  174  9月  9 20:24 hosts
drwx------. 2 root root    6  9月  9 20:24 mounts
-rw-r--r--. 1 root root   66  9月  9 20:24 resolv.conf
-rw-r--r--. 1 root root   71  9月  9 20:24 resolv.conf.hash
[zaki@example ~]$

この通り、100KBに達するとログがローテートされる。
ただ、見ればわかる通り、ローテートというよりはクリアされてしまうので、制限サイズの境界のタイミングでログがゼロになる瞬間ができてします。

世代数の設定

もう一つ設定すると良いオプションがローテートのファイル数。

max-file
$ sudo docker run -d --rm --log-opt max-size=100k --log-opt max-file=3 log-sample
f4ce850b1d1569c89f468d969fa5686f57891256807d47a13c1b3a04b0047561
$ sudo docker inspect f4ce | grep LogPath
        "LogPath": "/var/lib/docker/containers/f4ce850b1d1569c89f468d969fa5686f57891256807d47a13c1b3a04b0047561/f4ce850b1d1569c89f468d969fa5686f57891256807d47a13c1b3a04b0047561-json.log",

このままログの出力を見ていると

[zaki@example ~]$ sudo ls -lh /var/lib/docker/containers/f4ce850b1d1569c89f468d969fa5686f57891256807d47a13c1b3a04b0047561
合計 72K
drwx------. 2 root root    6  9月  9 20:36 checkpoints
-rw-------. 1 root root 2.9K  9月  9 20:36 config.v2.json
-rw-r-----. 1 root root  45K  9月  9 20:37 f4ce850b1d1569c89f468d969fa5686f57891256807d47a13c1b3a04b0047561-json.log
-rw-r--r--. 1 root root 1.5K  9月  9 20:36 hostconfig.json
-rw-r--r--. 1 root root   13  9月  9 20:36 hostname
-rw-r--r--. 1 root root  174  9月  9 20:36 hosts
drwx------. 2 root root    6  9月  9 20:36 mounts
-rw-r--r--. 1 root root   66  9月  9 20:36 resolv.conf
-rw-r--r--. 1 root root   71  9月  9 20:36 resolv.conf.hash

これが

[zaki@example ~]$ sudo ls -lh /var/lib/docker/containers/f4ce850b1d1569c89f468d969fa5686f57891256807d47a13c1b3a04b0047561
合計 152K
drwx------. 2 root root    6  9月  9 20:36 checkpoints
-rw-------. 1 root root 2.9K  9月  9 20:36 config.v2.json
-rw-r-----. 1 root root  97K  9月  9 20:37 f4ce850b1d1569c89f468d969fa5686f57891256807d47a13c1b3a04b0047561-json.log
-rw-r--r--. 1 root root 1.5K  9月  9 20:36 hostconfig.json
-rw-r--r--. 1 root root   13  9月  9 20:36 hostname
-rw-r--r--. 1 root root  174  9月  9 20:36 hosts
drwx------. 2 root root    6  9月  9 20:36 mounts
-rw-r--r--. 1 root root   66  9月  9 20:36 resolv.conf
-rw-r--r--. 1 root root   71  9月  9 20:36 resolv.conf.hash

こうなって

[zaki@example ~]$ sudo ls -lh /var/lib/docker/containers/f4ce850b1d1569c89f468d969fa5686f57891256807d47a13c1b3a04b0047561
合計 128K
drwx------. 2 root root    6  9月  9 20:36 checkpoints
-rw-------. 1 root root 2.9K  9月  9 20:36 config.v2.json
-rw-r-----. 1 root root  467  9月  9 20:37 f4ce850b1d1569c89f468d969fa5686f57891256807d47a13c1b3a04b0047561-json.log
-rw-r-----. 1 root root  98K  9月  9 20:37 f4ce850b1d1569c89f468d969fa5686f57891256807d47a13c1b3a04b0047561-json.log.1
-rw-r--r--. 1 root root 1.5K  9月  9 20:36 hostconfig.json
-rw-r--r--. 1 root root   13  9月  9 20:36 hostname
-rw-r--r--. 1 root root  174  9月  9 20:36 hosts
drwx------. 2 root root    6  9月  9 20:36 mounts
-rw-r--r--. 1 root root   66  9月  9 20:36 resolv.conf
-rw-r--r--. 1 root root   71  9月  9 20:36 resolv.conf.hash
[zaki@example ~]$

こうじゃ

設定なし

$ sudo docker run -d --rm log-sample
d76da2cccf741f100e10898ae4c2644a98e3a35848070bc6e652a2cb793fbba4
$ sudo docker inspect d76 | grep LogPath
        "LogPath": "/var/lib/docker/containers/d76da2cccf741f100e10898ae4c2644a98e3a35848070bc6e652a2cb793fbba4/d76da2cccf741f100e10898ae4c2644a98e3a35848070bc6e652a2cb793fbba4-json.log",
$ sudo ls -lh /var/lib/docker/containers/d76da2cccf741f100e10898ae4c2644a98e3a35848070bc6e652a2cb793fbba4/d76da2cccf741f100e10898ae4c2644a98e3a3584807
0bc6e652a2cb793fbba4-json.log
-rw-r-----. 1 root root 33K  9月  9 20:45 /var/lib/docker/containers/d76da2cccf741f100e10898ae4c2644a98e3a35848070bc6e652a2cb793fbba4/d76da2cccf741f100e10898ae4c2644a98e3a35848070bc6e652a2cb793fbba4-json.log
$ sudo ls -lh /var/lib/docker/containers/d76da2cccf741f100e10898ae4c2644a98e3a35848070bc6e652a2cb793fbba4/d76da2cccf741f100e10898ae4c2644a98e3a35848070bc6e652a2cb793fbba4-json.log
-rw-r-----. 1 root root 124K  9月  9 20:46 /var/lib/docker/containers/d76da2cccf741f100e10898ae4c2644a98e3a35848070bc6e652a2cb793fbba4/d76da2cccf741f100e10898ae4c2644a98e3a35848070bc6e652a2cb793fbba4-json.log

この通り100KB超えても普通に書き込みされる。

ちなみにログはこんな感じ。

$ sudo docker logs d76 | head -5
container started...
2020-09-09 11-44-50: NqQqgo00wBOqbFHzes2cQ6mOMet03upgyVh3C7QyuT8Ttr79ZcQF82jUhjfeb3sL
2020-09-09 11-44-50: vugDHpHItrnQZNhzoJCw925ClX486NrFoBgs4OhvqHYmgUbHXrN790dhuJtks7Nq
2020-09-09 11-44-50: oQZfA9oPlSO7RUl6yboTs75qpa6WIkjwD0EWxHfqB8ipftuM4EfoMeDj6uaKxTpC
2020-09-09 11-44-50: U62VsIkIzqau1eEinGIkpGEK1ckoesuVxTMDy9ZMZoWKXoAaektSt0LCyxh1V5o7

システムワイドに設定

オプション指定を忘れてると青天井に実行されても困るという場合は、デフォルトの設定にもできる。

docs.docker.com

前述の例のように、100KBで3世代であれば以下の通り。

$ cat /etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100k",
    "max-file": "3"
  }
}

設定変更したらサービスを再起動

$ sudo systemctl restart docker
$ sudo docker run -d --rm log-sample
69d476241d84e90522536bf8261c5fb2cae550a160258341999c5d3c812aaaf5
$ sudo docker inspect 69d | grep LogPath
        "LogPath": "/var/lib/docker/containers/69d476241d84e90522536bf8261c5fb2cae550a160258341999c5d3c812aaaf5/69d476241d84e90522536bf8261c5fb2cae550a160258341999c5d3c812aaaf5-json.log",
$ sudo ls -lh /var/lib/docker/containers/69d476241d84e90522536bf8261c5fb2cae550a160258341999c5d3c812aaaf5/69d476241d84e90522536bf8261c5fb2cae550a160258341999c5d3c812aaaf5-json.log
-rw-r-----. 1 root root 39K  9月  9 20:54 /var/lib/docker/containers/69d476241d84e90522536bf8261c5fb2cae550a160258341999c5d3c812aaaf5/69d476241d84e90522536bf8261c5fb2cae550a160258341999c5d3c812aaaf5-json.log

ファイルサイズをチェックしてると、この通り。

[zaki@example ~]$ sudo ls -lh /var/lib/docker/containers/69d476241d84e90522536bf8261c5fb2cae550a160258341999c5d3c812aaaf5
合計 152K
-rw-r-----. 1 root root  98K  9月  9 20:55 69d476241d84e90522536bf8261c5fb2cae550a160258341999c5d3c812aaaf5-json.log
drwx------. 2 root root    6  9月  9 20:53 checkpoints
-rw-------. 1 root root 2.9K  9月  9 20:53 config.v2.json
-rw-r--r--. 1 root root 1.5K  9月  9 20:53 hostconfig.json
-rw-r--r--. 1 root root   13  9月  9 20:53 hostname
-rw-r--r--. 1 root root  174  9月  9 20:53 hosts
drwx------. 2 root root    6  9月  9 20:53 mounts
-rw-r--r--. 1 root root   66  9月  9 20:53 resolv.conf
-rw-r--r--. 1 root root   71  9月  9 20:53 resolv.conf.hash
[zaki@example ~]$ sudo ls -lh /var/lib/docker/containers/69d476241d84e90522536bf8261c5fb2cae550a160258341999c5d3c812aaaf5
合計 128K
-rw-r-----. 1 root root  780  9月  9 20:55 69d476241d84e90522536bf8261c5fb2cae550a160258341999c5d3c812aaaf5-json.log
-rw-r-----. 1 root root  98K  9月  9 20:55 69d476241d84e90522536bf8261c5fb2cae550a160258341999c5d3c812aaaf5-json.log.1
drwx------. 2 root root    6  9月  9 20:53 checkpoints
-rw-------. 1 root root 2.9K  9月  9 20:53 config.v2.json
-rw-r--r--. 1 root root 1.5K  9月  9 20:53 hostconfig.json
-rw-r--r--. 1 root root   13  9月  9 20:53 hostname
-rw-r--r--. 1 root root  174  9月  9 20:53 hosts
drwx------. 2 root root    6  9月  9 20:53 mounts
-rw-r--r--. 1 root root   66  9月  9 20:53 resolv.conf
-rw-r--r--. 1 root root   71  9月  9 20:53 resolv.conf.hash

この制限を入れていないと、ホストOSのストレージをすべて使い切るまでファイル書き込みしてしまうので注意。(訳:やらかした)
どの設定も、目的はホストOSのリソースを喰いつくさないように安定性を高める。


追記: inspectで確認

ログサイズ制限を行ったコンテナをdocker inspectで確認すると以下の通り。

        "HostConfig": {
            [...]
            "LogConfig": {
                "Type": "json-file",
                "Config": {
                    "max-size": "100k"
                }
            },