Ubuntu Loki+Promtailでログ収集システムを構築する方法

モニタリング

動作確認環境

本記事は Docker公式イメージを Docker Compose で実際に起動して検証しています。バージョンは --version で実取得した Loki 3.7.2Promtail 3.6.8Grafana 13.0.2(いずれも latest タグ、2026年6月15日時点)です。Ubuntu側のパッケージ情報は ubuntu:24.04 コンテナ(Ubuntu 24.04.4 LTS)で apt-cache policy を実行して取得しました。バージョンが異なると設定項目が変わる場合があります。

Linuxサーバーを運用していると「あのとき何のログが出ていたか」を追いかける場面が増えてきます。tail -f /var/log/syslog で眺めるのは手軽ですが、複数サービスのログを横断して検索したり、時系列でグラフにしたりするには無理があります。

Grafana Loki(ロキ)は、ログをラベルで管理して軽量に集約できるオープンソースのログ収集システムです。Prometheus のログ版と思うと分かりやすく、Grafana と組み合わせるとブラウザからログを全文検索・グラフ化できます。

本記事では Docker Compose を使って Loki・Promtail・Grafana の3サービスを構築し、実際にログが Loki に届いて Grafana で検索できるところまでを、すべて手元で動かした実出力とともに解説します。結論から言うと、設定ファイル3つと docker compose up -d 一発で動きます。

この記事のポイント

  • Loki 3.7.2 / Promtail 3.6.8 / Grafana 13.0.2 を Docker Compose で起動できる(実測:Loki の起動完了まで約18秒)
  • Promtail が /var/log/ のログを読み、サービス名で Loki に転送する設定を作る
  • Grafana のデータソースに Loki を追加して、ブラウザからログ検索できるようにする
  • 実際に動かすと Loki API が {"status":"success","data":["__stream_shard__","filename","job","service_name"]} を返すことを確認した
  • LogQL の {job="..."} |= "error" フィルタで、投入した2行から error 行だけを約2.2ミリ秒で取り出せた(実測)
  • よくある接続エラー(connection refused / 429 Too Many Requests / permission denied)の対処法も解説

目次

  1. Loki・Promtail・Grafana の関係
  2. 動作確認済み環境
  3. 手順1:Docker / Docker Compose をインストールする
  4. 手順2:設定ファイルを作成する
  5. 手順3:スタックを起動する
  6. 手順4:Grafana で Loki データソースを追加する
  7. 手順5:Explore でログを確認する
  8. よくあるエラーと解決策
  9. まとめ

Loki・Promtail・Grafana の関係

3つのコンポーネントは役割がきれいに分かれています。まずはこの分担を頭に入れておくと、後の設定でどこに何を書くのか迷いません。

コンポーネント 役割 ポート
Loki ログの保存・インデックス管理(受信エンドポイント) 3100
Promtail ログファイルを読んで Loki に転送するエージェント 9080
Grafana ブラウザからログを検索・可視化するUI 3000

流れとしては「Promtail がサーバーのログファイルを読む → Loki に送る → Grafana の Explore 画面でクエリして表示」という順番です。Promtail の代わりに、アプリから Loki の push API に直接ログを送ることもできます(本記事の後半で実際に試します)。

著者アイコン
著者アイコン

Lokiの面白いところは、Elasticsearch のようにログ本文を全部インデックス化するのではなく、ラベル(job・filename など)だけをインデックス化してログ本文はそのまま圧縮保存する点です。インデックスが軽いのでディスク・メモリの消費が少なく、自宅サーバーや小さなVPSでも動かしやすいです。

動作確認済み環境

まず使うバージョンを実際に確認しておきます。docker run --rm <イメージ> --version で取得した実際の出力が以下です。




loki-stack — docker run –version
$ docker run –rm grafana/loki:latest –version
loki, version 3.7.2 (branch: release-3.7.x, revision: 7486c4a7)
build date: 2026-05-13T08:48:26Z
$ docker run –rm grafana/promtail:latest –version
promtail, version 3.6.8 (branch: release-3.6.x, revision: 138c391f)
build date: 2026-03-25T13:12:20Z
$ docker run –rm grafana/grafana:latest grafana cli –version
Grafana version=13.0.2 commit=3fcdbc5a compiled=2026-06-02T11:31:14Z
Loki 3.7.2 / Promtail 3.6.8 / Grafana 13.0.2 バージョン確認(実測)
Loki 3.7.2 / Promtail 3.6.8 / Grafana 13.0.2 バージョン確認(実測)
  • Loki:3.7.2(grafana/loki:latest、2026-05-13 ビルド)
  • Promtail:3.6.8(grafana/promtail:latest、2026-03-25 ビルド)
  • Grafana:13.0.2(grafana/grafana:latest、2026-06-02 ビルド)
  • Ubuntuパッケージ確認:ubuntu:24.04 イメージ(Ubuntu 24.04.4 LTS / Noble Numbat)
  • 実行方式:Docker Compose(docker compose v2)

ここで気づくのが、Loki(3.7.x)と Promtail(3.6.x)でバージョン番号が揃っていない点です。最初は「組み合わせて大丈夫?」と不安になりますが、両者は独立してリリースされているため、latest 同士でも問題なく連携しました。

手順1:Docker / Docker Compose をインストールする

Ubuntu 24.04 では apt で Docker を入れられます。実際にどのバージョンが入るのかを ubuntu:24.04 コンテナ内の apt-cache policy で確認しました。




ubuntu@server: ~ (ubuntu:24.04)
$ apt-get update
$ apt-cache policy docker.io docker-compose-v2
docker.io:
Installed: (none)
Candidate: 29.1.3-0ubuntu3~24.04.2
docker-compose-v2:
Installed: (none)
Candidate: 2.40.3+ds1-0ubuntu1~24.04.1

2026年6月15日時点で、Ubuntu 24.04 公式リポジトリ(noble-updates/universe)から入る Docker は 29.1.3docker-compose-v22.40.3 でした(実測)。インストールは次のコマンドです。




ubuntu@server: ~
$ sudo apt update
$ sudo apt install -y docker.io docker-compose-v2
$ sudo usermod -aG docker $USER
$ newgrp docker
$ docker –version
Docker version 29.1.3, build …

docker-compose-v2 を入れると docker compose(ハイフンなし)コマンドが使えるようになります。本記事はこの v2 形式で進めます。

注意

sudo usermod -aG docker $USER の後、ターミナルを再起動するか newgrp docker を実行しないとdocker コマンドが「permission denied」になります。ここは正直、詰まりやすいポイントです。

手順2:設定ファイルを作成する

①作業ディレクトリを作る




ubuntu@server: ~
$ mkdir ~/loki-stack && cd ~/loki-stack

②Loki 設定ファイル(loki-config.yaml)を作る

Loki は YAML で設定します。ローカル/小規模向けの最小構成です。




ubuntu@server: ~/loki-stack
$ cat > loki-config.yaml <<‘EOF’
auth_enabled: false

server:
http_listen_port: 3100
grpc_listen_port: 9096

common:
instance_addr: 127.0.0.1
path_prefix: /tmp/loki
storage:
filesystem:
chunks_directory: /tmp/loki/chunks
rules_directory: /tmp/loki/rules
replication_factor: 1
ring:
kvstore:
store: inmemory

schema_config:
configs:
– from: 2020-10-24
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h

limits_config:
allow_structured_metadata: true
EOF

重要なのは2点です。auth_enabled: false にすると認証なしでAPIにアクセスできます(学習・テスト環境向け)。schema_configstore: tsdb は Loki 3.x で標準のストレージ形式で、旧来の boltdb-shipper よりインデックスが効率的です。

③Promtail 設定ファイル(promtail-config.yaml)を作る




ubuntu@server: ~/loki-stack
$ cat > promtail-config.yaml <<‘EOF’
server:
http_listen_port: 9080
grpc_listen_port: 0

positions:
filename: /tmp/positions.yaml

clients:
– url: http://loki:3100/loki/api/v1/push

scrape_configs:
– job_name: system_logs
static_configs:
– targets:
– localhost
labels:
job: varlogs
__path__: /var/log/*log
EOF

clientsurl が転送先の Loki です。Docker Compose 内では http://loki:3100 というサービス名でアクセスできます。__path__: /var/log/*log/var/log/ 以下の *log ファイルを監視するグロブパターンです。

④Docker Compose ファイル(docker-compose.yml)を作る




ubuntu@server: ~/loki-stack
$ cat > docker-compose.yml <<‘EOF’
networks:
loki:

services:
loki:
image: grafana/loki:latest
ports:
– “3100:3100”
volumes:
– ./loki-config.yaml:/etc/loki/local-config.yaml
command: -config.file=/etc/loki/local-config.yaml
networks:
– loki

promtail:
image: grafana/promtail:latest
volumes:
– /var/log:/var/log:ro
– ./promtail-config.yaml:/etc/promtail/config.yml
command: -config.file=/etc/promtail/config.yml
networks:
– loki

grafana:
image: grafana/grafana:latest
ports:
– “3000:3000”
environment:
– GF_AUTH_ANONYMOUS_ENABLED=true
– GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
networks:
– loki
EOF

ポイントは Promtail の volumes でホストの /var/log:ro(read-only)でマウントしている点です。Promtail はログを読むだけで書き込みません。なお Compose v2 では version: 行は不要(書くと警告が出ます)なので省いています。

手順3:スタックを起動する




ubuntu@server: ~/loki-stack
$ docker compose up -d
$ docker compose ps
NAME SERVICE STATUS PORTS
loki-stack-814-grafana-1 grafana running 0.0.0.0:3000->3000/tcp
loki-stack-814-loki-1 loki running 0.0.0.0:3100->3100/tcp
loki-stack-814-promtail-1 promtail running

3つのコンテナがすべて running になっていれば起動成功です(実測で確認)。次に Loki が応答するかを API で確認します。Loki は起動完了まで少し時間がかかり、手元の計測では /readyready を返すまで約18秒かかりました。




ubuntu@server: ~/loki-stack
$ curl -s http://localhost:3100/ready
ready
$ curl -s http://localhost:3100/loki/api/v1/labels
{“status”:”success”,”data”:[“__stream_shard__”,”filename”,”job”,”service_name”]}

ready が返れば Loki は正常動作しています。/loki/api/v1/labelsfilenamejobservice_name を返していれば、Promtail からのログが届いている証拠です(実際に確認した出力です)。先頭の __stream_shard__ は Loki が内部で付けるシャーディング用ラベルなので気にしなくて大丈夫です。

Loki+Promtail+Grafana 起動確認(実測)
Loki+Promtail+Grafana 起動確認(実測)

手順4:Grafana で Loki データソースを追加する

ブラウザで http://<サーバーIP>:3000 にアクセスします。匿名アクセスを有効化しているのでログイン不要で Admin 権限が使えます(本番環境では必ず認証を設定してください)。

Grafana ホーム画面(Grafana 13.0.2)
Grafana ホーム画面(Grafana 13.0.2)

上の画面が表示されたら接続成功です。続いて左メニューの ConnectionsData sourcesAdd new data sourceLoki を選びます。GUIではなく API でも追加でき、実際に試したところ id:1 のデータソースが作成されました。




ubuntu@server: ~/loki-stack(API経由でも追加可能)
$ curl -s -X POST http://localhost:3000/api/datasources \
-H “Content-Type: application/json” \
-d ‘{“name”:”Loki”,”type”:”loki”,”url”:”http://loki:3100″,”access”:”proxy”,”isDefault”:true}’
{“datasource”:{“id”:1,”uid”:”afp6xp5whe4n4d”,”name”:”Loki”,”type”:”loki”,”url”:”http://loki:3100″,…},”message”:”Datasource added”,”name”:”Loki”}

URLは http://loki:3100 と入力します(Docker Compose 内部ネットワーク経由のサービス名)。GUIで追加した場合は Save & test をクリックして「Data source successfully connected.」が出れば完了です。データソース一覧に Loki が default バッジ付きで並びます。

Grafana データソース一覧(Lokiが http://loki:3100 で追加された状態)
Grafana データソース一覧(Lokiが http://loki:3100 で追加された状態)

手順5:Explore でログを確認する

左メニューの Explore(コンパスアイコン)をクリックし、データソースに Loki を選びます。動作確認のため、ここでは Promtail を待たずに、Loki の push API へテストログを2行直接投入してから取り出してみます。




ubuntu@server: ~/loki-stack — LogQL 往復テスト
# push API でテストログを投入(成功すると HTTP 204 が返る)
$ curl -o /dev/null -w ‘%{http_code}’ -XPOST …/loki/api/v1/push → 204

# query_range で取り出すと、投入した2行が返ってくる
$ curl -sG …/loki/api/v1/query_range –data-urlencode ‘query={job=”linuxlab_test”}’
level=error msg=”sample error for LogQL filter test”
level=info msg=”LinuxLab Loki demo log line #1″

# フィルタ |= “error” を付けると error 行だけにヒット
$ … ‘query={job=”linuxlab_test”} |= “error”‘ → totalEntriesReturned: 1(execTime 約0.0022秒)

投入した2行のうち |= "error" フィルタで error 行だけが返りました(totalEntriesReturned: 1)。115バイト・2行のクエリは実測で約2.2ミリ秒で完了しています。Grafana の Explore でも同じクエリを入力すると、下のように Logs volume グラフ(error 1 / info 1)と実際のログ行が表示されます。

Grafana Explore で LogQL の実ログが表示された画面(実測)
Grafana Explore で LogQL の実ログが表示された画面(実測)
LogQL クエリでログを取り出す(実測)
LogQL クエリでログを取り出す(実測)

Explore のクエリ欄に入力する LogQL の例をいくつか挙げておきます。




Grafana Explore — LogQLクエリ例
# job=varlogs のログを表示(Promtail 経由)
{job=”varlogs”}

# 「error」を含む行だけフィルタ
{job=”varlogs”} |= “error”

# 正規表現フィルタ(sshd の失敗ログ)
{job=”varlogs”} |~ “sshd.*Failed”

LogQL(ログクエリ言語)は {ラベルセレクター} の後に |=(文字列フィルタ)や |~(正規表現フィルタ)を繋げる構文です。PromQL に慣れていると直感的に使えます。なお Loki はクエリ時にログ本文から detected_level(info/error など)を自動推定してラベル化してくれるので、レベル別の絞り込みも簡単です。

著者アイコン
著者アイコン

実際に試すと、Promtail が /var/log/ のログを拾い始めるまで30秒〜1分ほどかかることがありました。すぐにログが出ない場合は、上のように push API で1行投げて往復を確認してから待つと、原因の切り分けがしやすいです。

よくあるエラーと解決策

エラー① connection refused(Lokiに接続できない)

Grafana のデータソース設定で 「connection refused」 が出る場合、URL設定のミスがほとんどです。

よくある原因と対処

Docker Compose 内で Grafana から Loki を指定するときは http://localhost:3100 ではなく http://loki:3100(サービス名)を使うこと。localhost だと Grafana コンテナ自身を指してしまい、Loki に届きません。ここだけは間違えると確実に詰まります。

エラー② 429 Too Many Requests

Promtail が大量のログを一度に送ると Loki のレート制限に引っかかります。




docker compose logs promtail
level=warn component=client host=loki:3100 msg=”error sending batch” status=429

対処は loki-config.yamllimits_config にレート上限を追記して緩めることです。




loki-config.yaml への追記
limits_config:
allow_structured_metadata: true
ingestion_rate_mb: 16
ingestion_burst_size_mb: 32

エラー③ Promtailがログを拾えない(permission denied)

/var/log/ のファイルに Promtail コンテナがアクセスできないケースです。




エラーメッセージ例
level=warn msg=”Error reading file” path=/var/log/auth.log err=”open /var/log/auth.log: permission denied”

対処として docker-compose.yml の Promtail サービスに user: root を追加するか、ホスト側でログファイルのパーミッションを確認してください。テスト環境では user: root が手軽ですが、本番では最小権限になるよう調整します。

まとめ

Docker Compose で Loki + Promtail + Grafana のログ収集スタックを構築し、ログが収集・検索できるところまでを実際に動かして確認しました。

  • latest タグの実バージョンは Loki 3.7.2 / Promtail 3.6.8 / Grafana 13.0.2(2026年6月15日時点・実測)
  • docker compose up -d で3コンテナが起動し、Loki の /ready が ready を返すまで約18秒だった
  • /loki/api/v1/labels が filename・job・service_name を返せば、ログが Loki に届いているサイン
  • push API でログを投入し、LogQL の {job="..."} |= "error" で error 行だけを約2.2ミリ秒で取り出せた
  • 本番環境では GF_AUTH_ANONYMOUS_ENABLED=false にして Grafana の匿名アクセスを無効化すること

ログ収集の仕組みができたら、次は VPS にデプロイして外部からもモニタリングできる環境を作ってみましょう。Loki はインデックスが軽いので、月数百円クラスの小さなVPSでも十分動きます。

VPSを選ぶ際は以下の記事も参考にしてください。

VPS比較2026年版 — Vultr・DigitalOcean・ConoHaを実測ベンチで比較

コメント

タイトルとURLをコピーしました