Dockerコンテナ上のアプリケーションのログのローテーション


Dockerコンテナ上のphpアプリケーションログを日時とサイズでローテションさせた時のメモ

・Monologにサイズでローテションしてくれる機能がなかったのでLogrotateを使ってローテションをしたって話。

構成
Docker + alpine + php + Monolog + logrotate + cron

Dockerfile

  • logrotateをインストール
RUN apk add logrotate
  • logrotateの設定ファイルをコピー
    予め、ログの設定を記述したファイルを用意しておきコンテナ内にコピーします。 下記の例の場合 local/log配下に設定ファイルを置いてある感じです。
RUN cp -rf local/log/logrotate.conf /etc/
COPY local/log/logrotate.d/php-log.conf /etc/logrotate.d
設定ファイル コピー先のパス 説明 パーミッション
logrotate.conf /etc/logrotate.conf デフォルトの設定ファイル 0600
logrotate.d /etc/logrotate.d 個別のログの設定ファイルを置くディレクトリ 0600
php-log.conf /etc/logrotate.d/php-log.conf 個別の設定ファイル 0600

ちなみに設定ファイルはこんな感じにしました。

local/log/logrotate.conf
# see "man logrotate" for details
# rotate log files weekly
weekly # 週1ローテ

# keep 4 weeks worth of backlogs
rotate 4 # デフォルトのログは4世代分まで管理(週1× 4回 = 1ヶ月分)

# create new (empty) log files after rotating old ones
create # ローテ後に空のファイルをつくる

# uncomment this if you want your log files compressed
#compress

# packages drop log rotation information into this directory
include /etc/logrotate.d # 個別ファイルを読み込む設定はコレ

# system-specific logs may be configured here

1日1回またはファイルサイズが10Mを超えたらローテーションを行う

local/log/logrotate.d/php-log.conf
/var/log/php/php-app.log {
    daily # 1日1回ローテーション
    missingok
    rotate 30 # 30世代分
    dateext # ローテ時には日付でsufix
    dateformat -%Y-%m-%d-%s
    delaycompress # ローテ後、圧縮を1回遅らせる
    size 10M # ファイルサイズが10Mを超えたらローテーションする
    su www-data www-data # 実行ユーザーを指定
}

entrypoint.sh

logrotateのcron設定を反映しcronを再起動

# setup entrypoint
COPY ./entrypoint.sh /usr/local/bin/
ENTRYPOINT ["entrypoint.sh"]

entrypoint.shはこんな感じ。

entrypoint.sh
cp -f /etc/periodic/daily/logrotate /etc/periodic/15min
crond restart
chmod o+x /var/log
mkdir /var/log/php
chown www-data:www-data /var/log/php
補足

logrotateのローテション作業はcronを介して行われます。
つまり、daily,weekly,hourlyのローテションもcronの設定次第というわけです。

/etc/periodic/daily/logrotateのファイルをcronでどのタイミングで見に行かせるかが要というわけですね。
alpineのcrontabの設定を覗いてみたら、日時、毎時、15分毎(もっとディレクトリあったかも)に下記のディレクトリを覗きにいって実行している設定になっており、logrotateはデフォルトでは日時フォルダ内にlogrotateを設置しています。
logrotateの実行タイミングを15分毎にすることによって、1日1回、またはログサイズが10Mを超えた時点でローテーションを行うようにしています。
※logrotateの実行タイミングが1日1回のままだとファイルサイズが10Mを超えていてもcronのタイミング(つまり1日1回)でしかローテーションは実行されません。

日時:/etc/periodic/daily
毎時:/etc/periodic/hourly
15分ごと:/etc/periodic/15min

logrotateのコマンド

コマンド 内容
logrotate -d /etc/logrotate.conf logrotate.confで設定されているログローテションの内容をデバックモード。※includeされるファイルも含む。(実際にはローテションは実行されない)
logrotate -d /etc/logrotate.d/php-log.conf /etc/logrotate.d/php-log.confのログローテーションをデバック。
logrotate -v /etc/logrotate.conf ログローテーションを実行。実行過程を標準出力に出力します。
cat /var/lib/logrotate.status ログの現在のバージョンと最後にローテションを実行した日時が確認できます。

もし参考にされる方がいましたらlogrotate -d /etc/logrotate.confは必ず実行することをお勧めします。
パーミッションや重複エラーなど何らかしらのエラーがあるとローテーションは実行されません。
phpアプリケーション側に合わせてディレクトリのパーミッションを緩くしたりするとパーミッションが緩いってlogrotateさんが怒ってきてローテーションを実行してくれません。

おわりに

前にやったことなので思い出しながらつらつらと書いています。
大体こんな感じだったと思います。
大したことやってないんですが、Monologにファイルサイズでローテーションする機能がなかったので。
Monologじゃなくても、PHPじゃなくても、ファイルサイズでローテーションすることが今後あるかもしれないと思って書き綴っています。