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 # 週１ローテ

# keep 4 weeks worth of backlogs
rotate 4 # デフォルトのログは4世代分まで管理（週１× 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を再起動

``` Dockerfile
# 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じゃなくても、ファイルサイズでローテーションすることが今後あるかもしれないと思って書き綴っています。