DockerのCMDでログファイルをtailする
Dockerは標準出力に出力したログなどはlogs
コマンドで確認することができますが、Dockerで動かすアプリケーションがファイルにログを出力している場合はlogs
コマンドで確認することができません。
このような場合は、CMDでtail -f
することが多いと思います。
CMD tail -f /var/log/cron.log
しかしこれだとlogs
コマンドに何も流れてきません。
そこでログファイルの中身をexec
コマンドで確認してみると正しくログが出力されています。
なにが起こっているのでしょうか。
Dockerのファイルシステム
原因はDockerが採用しているファイルシステムにあります。
DockerはUnion File System
というファイルシステムを採用していて、このファイルシステムはcopy-on-write
という方法で動作しています。
Union File System
やcopy-on-write
についてはこの記事がわかりやすいです。
直接的な原因は、CMDでtailしているログファイルはDocker imageに保存されているファイルであり、コピーされてログが書き込まれるようになったファイルではないためです。
対策
CMDでtailする前にcopy-on-writeを発生させればいいだけです。
やり方は色々あると思いますが、1つの例としてはこのようにCMDを書けば意図した通りに動きます。
CMD : >> /var/log/cron.log && tail -f /var/log/cron.log
なお、このようにCMDで&&
を使って複数コマンドを実行するときは、DockerのPID1とゾンビプロセスのことを考慮する必要が出てくるので注意しましょう。
参考
dockerfile - Output of `tail -f` at the end of a docker CMD is not showing - Stack Overflow