背景:ディスクフルという名の悪夢
サーバーがダウンし、午前3時に叩き起こされたことはありますか?原因を調べてみると、ディスク使用率が100%だった……。そんな経験をした人は少なくないはずです。私も以前、eコマースプロジェクトのマイクロサービスをデプロイした際に苦い経験をしました。ログをdebugモードにしたまま容量制限を忘れてしまい、わずか48時間で1つのログファイルが65GBまで肥大化。結果として、VPSのルートパーティションを完全に使い果たしてしまいました。
デフォルトでは、Dockerはjson-fileロギングドライバーを使用します。このドライバーは、すべての出力(stdout/stderr)をホスト上のJSONファイルに黙々と記録し続けます。制限を設けない場合、このファイルはディスクに1バイトの空きも無くなるまで無限に膨れ上がります。そうなれば、データベースの書き込みは止まり、サービスは連鎖的に停止し、あなたは後始末のために午前中を丸々潰すことになるでしょう。
このようなホラーシナリオを避けるために、Log Rotation(ログローテーション)は必須のテクニックです。簡単に言えば、ログファイルのサイズを制御し、許容値を超えた場合に古い記録を自動的に削除する仕組みのことです。
コンテナのログ制限を設定する3つの効果的な方法
単一のコンテナを実行しているのか、サーバー全体を管理しているのかによって、以下の3つのアプローチから最適なものを選んでください。
1. Docker Runコマンドによるクイック設定
この方法は、単一のコンテナを素早くテストしたい場合に適しています。起動コマンドに直接 --log-opt フラグを追加するだけです。
docker run -d \
--name nginx-proxy \
--log-driver json-file \
--log-opt max-size=10m \
--log-opt max-file=3 \
nginx
パラメータの説明:
max-size=10m: ログファイルが10MBに達すると、ローテーションが実行されます。max-file=3: システムは最大3つの古いログファイルのみを保持します。4つ目のファイルが生成されると、最も古いファイルが削除されます。
2. Docker Composeでの設定
実務では、Docker Composeを使用することが一般的です。.yml ファイルにログ設定を記述することで、インフラをコードとして管理(IaC)でき、サーバー移行時の再利用も容易になります。
services:
api-service:
image: node:18-alpine
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "5"
db-postgres:
image: postgres:15
logging:
driver: "json-file"
options:
max-size: "20m"
max-file: "3"
経験則からのアドバイス:データベースのような重要なサービスでは、max-file を5〜10程度に増やしておくことをお勧めします。これにより、過去のエラー追跡(トレース)が容易になります。
3. サーバー全体のグローバル設定(推奨)
これが最も効率的な「設定して放置(set and forget)」できる方法です。コンテナごとに設定する代わりに、Docker Daemonに共通のルールを設定します。それ以降に作成されるすべてのコンテナは、自動的にこのルールに従います。
/etc/docker/daemon.json にあるDocker設定ファイルを開く(または新規作成する)してください:
sudo nano /etc/docker/daemon.json
ファイルに以下の内容を貼り付けます:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
最後に、変更を適用するためにDockerを再起動します:
sudo systemctl restart docker
重要な注意点: Docker Daemonを再起動すると、実行中のコンテナが一時的に切断されます。また、この設定は新しく作成されるコンテナにのみ適用されます。既存のコンテナは、再作成(recreate)するまで以前の設定のまま維持されます。
ディスク容量が100%になった時の緊急対処法
もし、サーバーが「瀕死の状態」でこの記事を読んでいるなら、焦って rm コマンドでログファイルを削除しないでください。プロセスがファイルを掴んだままだと、Dockerが即座に容量を解放しない場合があります。最も確実な方法は、ファイルを空にする(truncate)ことです:
# すべてのDockerログファイルを即座に空にする
sudo sh -c "truncate -s 0 /var/lib/docker/containers/*/*-json.log"
このコマンドは、ログファイルの容量を一瞬で0バイトにし、サービスを再起動することなくサーバーを「息を吹き返した」状態にします。
まとめ
ログ管理は、ローカル環境ではジュニアエンジニアに軽視されがちです。しかし、数百万のリクエストが発生する本番環境では、ログは諸刃の剣となります。
私からのアドバイスは、新しいサーバーをセットアップしたらすぐに daemon.json を設定することです。もしアプリケーションが分析のために長期的なログ保存を必要とするなら、アプリケーションサーバーのディスクを消費させるのではなく、ELK StackやGraylogのような専用システムにログを転送するようにしましょう。小さなテキストファイルのせいで、巨大なシステム全体をダウンさせないように気をつけてください!

