サーバー上でDocker Composeを使ってサービスを動かしていると,ログを直接確認したい場面がある.通常は docker compose logs で十分だが,ログファイルのサイズ確認,調査用の退避,監視設定などでは,ホスト上のログファイルの場所を知りたくなる.

Docker Composeが独自のログファイルを作るわけではない.実際には,Composeが起動した各コンテナのログをDocker Engineが管理する.そのため,ログファイルの場所はComposeファイルから推測せず,対象コンテナを特定してDockerに確認する.

まずはComposeのログを見る

普段の確認なら,これで足りることが多い.

1docker compose logs --tail 100 -f

--tail 100 は,ログの末尾から直近100行だけを表示する指定だ.過去ログが大量にあるコンテナでも,最初に表示する量を絞れるため,確認したい箇所へたどり着きやすい.-f は新しく出力されるログを追い続ける指定のため,この例では直近100行を表示したあと,その後のログをリアルタイムで追跡する.

特定サービスだけを見る場合は,サービス名を指定する.

1docker compose logs --tail 100 -f web

docker compose logs は,Composeプロジェクトに含まれるコンテナのログをまとめて表示するコマンドだ.ログファイルの実体を直接開いているわけではなく,Docker Engineが持っているログを読み出している.

対象コンテナを確認する

Composeファイル docker-compose.yaml があるディレクトリで,コンテナの状態を確認する.

1docker compose ps

サービス名からコンテナIDだけを取得する場合は,-q を使う.

1docker compose ps -q web

以降では,web サービスのコンテナを調べる例とする.

1container_id=$(docker compose ps -q web)

サービス名が分からない場合は,Docker側から起動中のコンテナ一覧を見る.

1docker ps --format 'table {{.ID}}\t{{.Names}}\t{{.Image}}\t{{.Status}}'

Composeで起動したコンテナ名には,プロジェクト名やサービス名が含まれることが多い.対象のコンテナ名が分かれば,コンテナIDの代わりに名前を指定してもよい.

ログドライバーを確認する

Dockerのログ保存方法は,ログドライバーによって変わる.まず対象コンテナのログドライバーを確認する.

1docker inspect -f '{{.HostConfig.LogConfig.Type}}' "$container_id"

Dockerの標準設定では json-file が使われる.AlmaLinuxでDockerを公式リポジトリから入れた直後なら,多くの場合はこの形式になる.Dockerデーモン全体の標準ログドライバーは,次のコマンドで確認できる.

1docker info --format '{{.LoggingDriver}}'

ただし,既存コンテナは作成時点のログ設定を持つ.Dockerデーモン側の設定を変更しても,作成済みコンテナのログドライバーは自動では変わらない.

ログファイルのパスを確認する

json-file を使っているコンテナなら,docker inspectLogPath でログファイルの場所を確認できる.

1docker inspect -f '{{.LogPath}}' "$container_id"

出力例は次のようになる.

1/var/lib/docker/containers/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-json.log

このパスはコンテナごとに異なるため,手で組み立てずに docker inspect で取得する方が確実だ.

ファイルサイズを確認する.

1log_path=$(docker inspect -f '{{.LogPath}}' "$container_id") 2sudo ls -lh "$log_path"

中身を追う場合は tail を使う.

1sudo tail -n 100 -f "$log_path"

/var/lib/docker 配下はroot権限が必要になることが多い.一般ユーザーでDockerコマンドを実行できても,ログファイルを直接読むときは sudo が必要になる場合がある.

コンテナ名から直接調べる

コンテナ名が分かっている場合は,変数を使わずにそのまま指定できる.

1docker inspect -f '{{.LogPath}}' one-coder-web-1

コンテナIDでも指定できる.

1docker inspect -f '{{.LogPath}}' 123456789abc

docker ps に表示される短いコンテナIDでも,多くの場合は指定できる.同じ先頭文字列を持つコンテナが複数ある場合は曖昧になるため,そのときは長いIDを使う.

journaldを使っている場合

ログドライバーが journald の場合,ログは通常のJSONファイルではなくsystemd journalへ送られる.この場合は LogPath が空になることがある.

1docker inspect -f '{{.HostConfig.LogConfig.Type}}' "$container_id" 2docker inspect -f '{{.LogPath}}' "$container_id"

journald のログは journalctl で確認する.

1container_name=$(docker inspect -f '{{.Name}}' "$container_id" | sed 's#^/##') 2sudo journalctl CONTAINER_NAME="$container_name" -n 100 -f

直近の起動以降に絞る場合は -b を付ける.

1sudo journalctl -b CONTAINER_NAME="$container_name" -n 100 -f

ログドライバーによって,確認方法は変わる.json-file なら LogPathjournald なら journalctl,という切り分けで考えると分かりやすい.

ログが大きくなる前に設定する

json-file のまま何も設定しないと,ログが増え続けてディスクを圧迫することがある.本番運用ではログローテーションを設定しておく.

Dockerデーモン全体に設定する例は次のとおり.

1{ 2 "log-driver": "json-file", 3 "log-opts": { 4 "max-size": "10m", 5 "max-file": "3" 6 } 7}

設定ファイルは通常 /etc/docker/daemon.json に置く.変更後はDockerを再起動する.

1sudo systemctl restart docker

この設定は,新しく作成するコンテナに適用される.既存のComposeコンテナへ反映したい場合は,コンテナを作り直す必要がある.

1docker compose down 2docker compose up -d

down によってコンテナは削除されるが,名前付きボリュームは通常残る.それでも本番環境で実行する前に,Composeファイルのボリューム定義とバックアップ状況を確認する.

よく使う確認手順

実際には,次の流れを覚えておけばよい.

1# 対象サービスのコンテナIDを取得する 2container_id=$(docker compose ps -q web) 3 4# ログドライバーを確認する 5docker inspect -f '{{.HostConfig.LogConfig.Type}}' "$container_id" 6 7# json-fileの場合,ログファイルの場所を確認する 8docker inspect -f '{{.LogPath}}' "$container_id" 9 10# ファイルサイズを見る 11log_path=$(docker inspect -f '{{.LogPath}}' "$container_id") 12sudo ls -lh "$log_path" 13 14# ログを追う 15sudo tail -n 100 -f "$log_path"

Composeのログファイルを探すときは,固定パスを暗記するより,対象コンテナを特定して docker inspect で確認する方が確実だ.Composeはサービスをまとめて扱うための仕組みであり,ログの保存場所は最終的にDocker Engineのログドライバーが決める.

参考