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