DockerでDozzleを導入:HomeLab向けリアルタイムコンテナログ監視

HomeLab tutorial - IT technology blog
HomeLab tutorial - IT technology blog

手動でのログ追跡に伴うストレス

自宅サーバーで多数のサービスを運用していると、ターミナルが散乱しがちです。アプリがクラッシュするたびにホストへSSH接続し、docker psを実行してコンテナ名を確認したうえで、docker logs -f --tail 100 app_nameを実行することになります。特に頭を悩ませるのは、相互に依存するサービスのデバッグです。例えば、NextcloudがRedisやPostgreSQLと連携中に500エラーを出力した場合、1つのリクエストの流れを追うためだけに、3つのターミナルウィンドウを同時に開いて監視しなければなりません。

Grafana LokiやElasticsearchのようなエンタープライズ向けスタックを利用すればログ集約は解決できますが、それ相応のハードウェアリソースが要求されます。ELKスタックやLokiスタックは、本格的なトラフィックを処理する前であっても2GBから4GBものRAMを消費することがあります。16GBのミニPCやRaspberry Pi 5で構成された環境において、時折発生するエラートレースを読むだけのためにコンピュートリソースの4分の1を割り当てるのは合理的ではありません。

Dozzleとは?インデックス不要のリアルタイムストリーミング

Dozzleは徹底的に無駄を削ぎ落としたアプローチを採用しています。ログファイルを個別のデータベースエンジンに解析・インデックス化・保存することはありません。その代わりに、ホストのDockerデーモンソケット(/var/run/docker.sock)に直接接続し、Dockerから標準出力(stdout)および標準エラー出力(stderr)を直接読み取ります。そして、Server-Sent Events(SSE)を経由してそれらのログ行をブラウザに直接配信します。

HomeLabにおける主なメリット

  • 極小のフットプリント:データベースエンジンやインデックス処理のワーカーを持たないため、Dozzleのアイドル時のメモリ消費量はわずか15MB〜30MB程度です。アクティブなストリームを開かない限り、CPU使用率もほぼゼロを維持します。
  • 瞬時のライブストリーミング:ポーリングや手動でのページ再読み込みを必要とせず、ミリ秒単位でstdoutおよびstderrのイベントをブラウザのタブに受信します。
  • 正規表現・文字列フィルタリング:FATALなどのキーワードや、HTTP/1.1" 5[0-9]{2}といった特定のHTTPステータスパターンを用いて、トレースバックを迅速に特定できます。
  • マルチホストのエージェントモード:コンピュートクラスターやメディアサーバーなどのセカンダリノードにあるリモートのDockerエンジンを連携させ、1つのブラウザタブに統合表示できます。
  • リアルタイムのリソースメトリクス:ログ出力のすぐ上に、コンテナごとのCPU使用率やメモリ使用上限のグラフが並んで表示されます。

Docker ComposeによるDozzleのデプロイ

既存のDockerホストがあれば、わずか2分でDozzleを稼働させることができます。まずは、Composeスタック専用のディレクトリを作成します:

mkdir -p ~/homelab/dozzle && cd ~/homelab/dozzle
nano docker-compose.yml

ファイルに以下のサービス設定を追加します:

services:
  dozzle:
    container_name: dozzle
    image: amir20/dozzle:latest
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    ports:
      - "8080:8080"
    environment:
      DOZZLE_LEVEL: info
      DOZZLE_NO_ANALYTICS: "true"

デタッチモードでサービスを起動します:

docker compose up -d

ブラウザを開き、http://<サーバーのIPアドレス>:8080にアクセスします。左側のサイドバーに、ホスト上の実行中および停止中のコンテナが一覧表示されます。コンテナを選択すると、ライブログフィードが即座に表示されます。

現場で役立つ実践テクニックとセキュリティ強化

基本設定だけでもすぐに動作しますが、ローカルネットワーク上でDozzleを安全に運用するには、いくつかの実用的な調整が必要です。

1. Dockerソケットを読み取り専用モードでマウントする

/var/run/docker.sockへの完全な書き込み権限をコンテナに与えると、ホストのプロセスに対するroot権限での制御を許すことになります。万が一Webコンテナに脆弱性があった場合、攻撃者は書き込み可能なソケットを利用して基盤のOSへエスケープするリスクがあります。Dozzleが必要とするのはログストリームとコンテナステータスのメタデータ読み取りのみです。ボリュームマウントに:roフラグを追加し、常に読み取り専用アクセスを強制してください:

volumes:
  - /var/run/docker.sock:/var/run/docker.sock:ro

2. 認証機能を設定してWebインターフェースを保護する

保護されていないDozzleインスタンスをローカルサブネットやリバースプロキシ経由で公開してはいけません。本番環境のログには、環境変数、内部IP体系、認証トークン、機密性の高いSQLクエリなどが頻繁に含まれています。

Dozzleには組み込みのユーザーファイルハンドラーが用意されています。永続設定用のフォルダーと初期設定のusers.ymlを作成します:

mkdir -p data
cat <<EOF > data/users.yml
users:
  - username: admin
    password: 強力なパスワードを設定してください123!
    name: ラボ管理者
    email: [email protected]
EOF

このファイルを/data/users.ymlにマウントし、簡易認証を有効化します:

services:
  dozzle:
    container_name: dozzle
    image: amir20/dozzle:latest
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./data/users.yml:/data/users.yml:ro
    ports:
      - "8080:8080"
    environment:
      DOZZLE_AUTH_PROVIDER: simple
      DOZZLE_NO_ANALYTICS: "true"

docker compose up -dで変更を適用すると、ログインプロンプトによるアクセス制限が有効になります。

3. Dockerログのローテーションを全体に適用する

Dozzleは、ディスク上の/var/lib/docker/containers/配下に保存されたDocker標準のJSONログファイルから直接読み取ります。デフォルトでは、Dockerはこれらのファイルをローテーションしません。ログ出力の多いデータベースやリバースプロキシが1日に200MBのログを出力し続けると、最終的にストレージを圧迫します。そうなると、Dozzleがギガバイト単位の巨大なファイルをストリーミングしようとして動作が著しく低下します。

/etc/docker/daemon.jsonにサイズ制限を設定することで、ホスト全体でこの問題を防ぐことができます:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "20m",
    "max-file": "3"
  }
}

このルールにより、Dockerはコンテナごとに保持するログの総容量を最大60MB(20MBファイル×3世代)に制限します。稼働中のコンテナを停止させることなく新しいコンテナにポリシーを適用するには、デーモンをリロードします:

sudo systemctl reload docker

4. エージェントを用いてマルチノードクラスタを監視する

マシンごとに個別のDozzle Webダッシュボードを用意する必要はありません。HomeLab内にストレージ用NAS、Intel N100搭載ミニPC、Raspberry Piクラスタなどが混在していても、Dozzleエージェントを利用して一元管理できます。

各サテライトマシンに軽量なエージェントコンテナをデプロイします:

services:
  dozzle-agent:
    container_name: dozzle-agent
    image: amir20/dozzle:latest
    command: agent
    restart: unless-stopped
    ports:
      - "7007:7007"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro

次に、メインのDozzleダッシュボードサーバー側で、それらのノードの内部IPアドレスとポート7007を指定して接続設定を行います:

services:
  dozzle:
    container_name: dozzle
    image: amir20/dozzle:latest
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    ports:
      - "8080:8080"
    environment:
      DOZZLE_REMOTE_HOST: "192.168.1.50:7007,192.168.1.51:7007"

ダッシュボードの左メニューにノード名ごとにグループ化されてコンテナが表示されます。ブラウザウィンドウを切り替えたり複数のSSHセッションを管理したりすることなく、複数マシンにまたがるログをフィルタリングできます。

HomeLabの可観測性に最適なツール

Dozzleは、扱いにくいターミナルウィンドウと、リソース消費の激しいエンタープライズ向け可観測性スタックとの間の隙間を埋めてくれるツールです。データベースワーカーを常駐させず、読み取り専用のDockerソケットを通じて直接ストリーミングするため、ハードウェアリソースを本来のアプリケーション実行に集中させることができます。適切なソケット権限設定、ユーザー認証、ディスクログローテーションを組み合わせることで、自宅ネットワーク上に高速で信頼性の高いログ監視環境を構築できます。

Share: