🦈

Dockerログを収集して可視化してみた

2021/07/09に公開

目的

Dockerで色々コンテナを立てて開発を行なっていると、さまざまなログが各コンテナの指定形式&場所に吐き出されます。
小規模な開発であれば、例えばGoコンテナにアクセスして直にサーバー立ててそこで直接ログを見たりすればいいのですが、Queueサービスとかコンテナ間通信する場合他のコンテナのログも見る必要があったりします。
そんな時にログが一箇所に集約されていないと面倒だなと思い、コンテナのアプリケーションログを収集し分析できるツールを探していたところLokiを見つけたので試してみました。
EFKを使用してもいいと思ったけど、Prometheusを今後使用したい欲求があったので今回はその前段として
Loki + Promtail + Grafanaを使用してアプリケーションログにフォーカスしてログ分析をしてみました。
※ローカルでまずは軽く試してみます。

構成

.
├── docker
│   ├── loki
│   │   └── data
│   └── nginx
│       ├── Dockerfile
│       ├── default.conf
│       └── index.html
└── docker-compose.yaml

こちらプルってくればそのまま使えます。
https://github.com/y-saiki1/article-loki

DockerでGrafana/Loki/Promtailを構築する

Lokiのインストール手順を確認するためにGraganaの公式を確認
https://grafana.com/docs/loki/latest/installation/

すると以下の5つのインストール方法があるようです

  • Install using Tanka (recommended)
  • Install through Helm
  • Install through Docker or Docker Compose
  • Install and run locally
  • Install from source

tankaやhelmはk8s用なので、今回はDockerを使用してローカルでサクッと試してみるので

  • Install through Docker or Docker Compose

こちらを使用していきます。

※ページにアクセスすると以下の文言が出ている通り、本番で使用する場合はk8s前提なんですかね

You can install Loki and Promtail with Docker or Docker Compose if you are ?evaluating, testing, or developing Loki. For production, we recommend installing with Tanka or Helm.

アクセスしたページの最下部に

wget https://raw.githubusercontent.com/grafana/loki/v2.2.1/production/docker-compose.yaml -O docker-compose.yaml

とあるので、実行すると以下ファイルがダウンロードできます

version: "3"

networks:
  loki:

services:
  loki:
    image: grafana/loki:2.0.0
    ports:
      - "3100:3100"
    command: -config.file=/etc/loki/local-config.yaml
    networks:
      - loki

  promtail:
    image: grafana/promtail:2.0.0
    volumes:
      - /var/log:/var/log
    command: -config.file=/etc/promtail/config.yml
    networks:
      - loki

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    networks:
      - loki

しかしこのままのdocker-compose.ymlを実行したところでDockerコンテナログをLokiに集積することはできません。
理由は、
Promtailをサービスとして立ち上げたとしても、Dockerのログ取得はlogging設定で行われるのでコンテナを立ち上げて同行する問題ではないからです。

Dockerのコンテナログを取得してLokiに集積させるためにはサービスにpromtailを追加するのではなく、Dockerのコンテナログ取得にpromtailを絡ませる必要があります。

そのために以下のプラグインが必要になります。

docker plugin install grafana/loki-docker-driver:latest --alias loki --grant-all-permissions

※この辺は公式にあるので参考にしてみてください
※Windowsはdocker pluginをサポートしていないとか書いてあったので注意です。
https://grafana.com/docs/loki/latest/clients/docker-driver/

プラグインがインストールできたら、docker-compose.ymlを編集していきます。

version: "3"

services:
  web:
    logging:
      driver: loki
      options: 
        loki-url: http://127.0.0.1:3100/loki/api/v1/push
    build: 
      context: .
      dockerfile: ./docker/nginx/Dockerfile
    ports: 
      - 10051:80
    volumes:
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
      - ./docker/nginx/index.html:/var/www/html/index.html
    depends_on: 
      - loki

  loki:
    image: grafana/loki:2.0.0
    ports:
      - "3100:3100"
    command: -config.file=/etc/loki/local-config.yaml
    volumes:
      - ./docker/loki/data:/data/loki

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"

変更した点は、
Lokiにログデータを送るためのサービスとしてnginxコンテナを定義してます。
実際にログを吐くサービスがなければ検証できないので。

あと、logging設定で書かれている

  • driver: "loki"
  • options: loki-url: http://localhost:3100/loki/api/v1/push

は、プラグインでインストールしたgrafana/loki-docker-driver⇦これがあるので、lokiを指定できます。
driverの名前がlokiになってますが、promtailがどのlokiサーバーにログを配信するかの設定です。
あとはnginxの設定ファイルを以下のようにして、初期ページ用のHTMLを書いてボリュームでコンテナと同期させてあげれば、ログがlokiに配信されるはずです。

server {
  listen 80;
  root /var/www/html;
  index index.html;
  charset utf-8;
  client_max_body_size 20M;
}

↑構成のセクションにある./docker/nginx/default.confの内容です。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>Hello Loki</h1>
</body>
</html>

↑構成のセクションにある./docker/nginx/index.htmlの内容です。

では、docker compose up -dでコンテナ群を立ち上げ、localhost:10051にアクセスしてアクセスログがlokiに転送されているか確認してみましょう。

ログを実際に確認する

まずLokiでログを確認するには、可視化ツールのGrafanaにアクセスします。アクセスはymlに書いてあるとおり、localhost:3000でアクセスしましょう。
アクセスすると、id/passでログインする画面が表示されます

こちらの画面に以下情報を入力してログインしましょう
id: admin
pass: admin
と入力するとログインが完了し、パスワードの変更を求められますので、適当に決めちゃってください。

ログインが完了するとトップページに遷移するので、画像の赤枠の部分をクリックして
Grafanaで可視化するためにLokiをsourceとして指定しましょう。

色々と設定項目がありますが、URLだけ指定するだけで動くので設定しましょう。
※Grafanaはコンテナで稼働しているので、Lokiを指定するときはエイリアスでOKです。

最後にSave&Testを実行すると、押したボタンのすぐ上に
Data source connected and labels found.
と表示されるはずです。
表示されない場合は、押したボタンのすぐ上に502 Bat GateWayが出てたりするので、Lokiコンテナが立ち上がっているか、エイリアスが正しいか確認してみましょう。

ここまでできたら、繋ぎ込みは完了なので、次はログの出力とログの表示です。
ログの出力は、localhost:10051にアクセスすればnginxのアクセスログがdocker側にキャッチされLokiに転送されます。(localhost:10051にアクセスして、Helloが表示されない場合はnginxコンテナを確認)
次にログの表示ですが、Grafanaで画像にあるようにexploreをクリックして、Log browserをクリックしましょう

クリックできたら以下が表示されていると思うので、赤枠の通りに選択してください

ここのcontainer_name以外にも項目があると思いますが、これはdockerのログのラベルです。
今回はコンテナ単位で表示していますが、docker-compose.ymlに記載されている全てのサービスを見たければcompose_projectを選択してShow logsボタンを押すと全てのコンテナのログが見れます。

container_nameを選択して、nginxコンテナ(article-loki_web_1)を選択すると以下のようにアクセスログが可視化されているはずです。

nginxコンテナのログだけでしたが、ざっくりと簡単にログが追えましたね。
httpステータスの404で絞るとかそういうこともできると思うのですが、長いので一旦導入までとします。

以上です。

もっとサクッと試したい方は以下
https://grafana.com/tutorials/grafana-fundamentals/?utm_source=grafana_gettingstarted

Discussion