5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

開発環境でRailsのログをFluentdでElasticsearchに送ってKibanaで見るための環境をDockerで作る

Last updated at Posted at 2021-01-27

目的

fluentdやkibanaの使い方を知らなかったので、勉強のために開発環境にDockerでfluentdやkibanaを触れる環境を作ってみました。
この記事のゴールは、fluentdを通してElasticsearchにログを送りKibanaでRailsのログを見ることです。

記事の最後まで進めると、Kibanaでこんな風にRailsのログが表示されます。
スクリーンショット 2021-01-27 18.37.57.png

概要

104429333-d7f65f80-55c8-11eb-9f20-81ea36226fcb.png

フォルダ構成

トップにあるDockerfileはRails用です。
dockerフォルダにはElasticsearch、fluentd、Kibana、MySQL、NginxのDockerfileをおいています。

$ ls
Dockerfile docker-compose.yml docker/ entrypoint.sh
$ tree -L 2 docker
docker
├── elasticsearch
│   └── Dockerfile
├── fluentd
│   ├── Dockerfile
│   └── fluent.conf
├── kibana
│   └── Dockerfile
├── mysql
│   └── Dockerfile
└── nginx
    ├── Dockerfile
    └── nginx.conf

バージョン

対象 バージョン
ruby 2.7.2
rails 6.1
mysql 5.7
nginx 1.19.6
elasticsearch 7.10.1
kibana 7.10.1
fluentd 1.12-1
docker 20.10.2

Rails環境作成

まずはRailsを動かすためにファイルを作っていきます。DBの設定もここで書いていきます。

1. まずは以下のコマンドで必要なファイルを作ります

touch {Dockerfile,Gemfile,Gemfile.lock,entrypoint.sh,docker-compose.yml,.dockerignore}

2. Dockerfileの中身を書いていきます

手順1で作ったDockerfileに以下のコードを書いてください

FROM ruby:2.7-slim-buster

RUN apt-get update -qq && \
    apt-get install -y --no-install-recommends \
    vim locales build-essential \
    libpq-dev libmariadb-dev curl npm && \
    npm install -g yarn n && \
    n 15.6

ENV APP_ROOT /app
WORKDIR $APP_ROOT

COPY Gemfile Gemfile.lock $APP_ROOT/

RUN gem update --system && gem install bundler:2.1.4

RUN RAILS_ENV=development bundle install && yarn install --frozen-lockfile


COPY . $APP_ROOT/
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

3. Gemfileの作成

手順1で作ったGemfileに以下を記述

source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.7.2'

gem 'rails', '~>6'

4. entrypoint.sh

手順1で作ったentrypoint.shに以下を記述

#!/bin/bash
set -e
rm -f /app/tmp/pids/server.pid
exec "$@"

5. dockerフォルダを作ってそこにMySQLのDockerfileを作成する

docker/mysqlフォルダ作成し

mkdir -p docker/mysql

mysql用のDockerfileを作成し

touch docker/mysql/Dockerfile

docker/mysql/Dockerfileには以下を記述します

FROM mysql:5.7

6. docker-compose.ymlを作成


version: "3.7"
services:
  db:
    build: ./docker/mysql/
    environment:
      MYSQL_DATABASE: root
      MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
      TZ: Asia/Tokyo
    expose:
      - 3306
    volumes:
      # 初期データを投入するSQLが格納されているフォルダ
      - ./docker/mysql/mysql_init:/docker-entrypoint-initdb.d
      # 永続化するときにマウントするフォルダ
      - ./docker/mysql/mysql_data:/var/lib/mysql
  app:
    build: .
    command: /bin/sh -c "rm -f /app/tmp/pids/server.pid && bundle exec rails s -b '0.0.0.0'"
    environment:
      DATABASE_HOST: db
      DATABASE_PORT: 3306
      DATABASE_USER: root
      RAILS_ENV: development
    expose:
      - 3000
    port:
      - 3000:3000
    depends_on:
      - db
    #ポート待受していないコンテナがすぐ終了してしまうのを防ぐ
    tty: true
    # コンテナの標準に入力をオープンにする
    stdin_open: true
    volumes:
      - .:/app

7. .dockerignoreファイルに以下を記述

tmp/
!tmp/pids/
node_modules/
vendor/bundle/

8. Dockerでrails newを実行

docker-compose run --no-deps app rails new . --force --database=mysql

これの実行が完了するまで数分の時間がかかるので気長に待ちましょう...

9. DBの作成

先程のコマンドの実行が完了したらconfig/database.ymlというファイルが作られています。そのファイルのhostを以下のように編集します。
localhostからdbという名前に変えてください。

default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
- host: localhost
+ host: db

そしたらrailsをDockerの立ち上げて

docker-compose up --build

別のターミナルでDBを作成するコマンドを実行します。

$ docker-compose run app rails db:create
Starting rails-monitoring_test_db_1 ... done
Created database 'app_development'
Created database 'app_test'

これが完了したら、http://localhost:3000 にアクセスしてみましょう。

この画面が出たら起動成功です!

スクリーンショット 2021-01-27 16.50.15.png

Nginxを作成

続いてNginxの環境を作って行きます。

1. Nginxに関する設定を置くフォルダを作成

mkdir -p docker/nginx/

2. Nginx用のDockerfileと設定ファイルを作成

touch docker/nginx/{Dockerfile,nginx.conf}

3. NginxのDockerfileを書きます

docker/nginx/Dockerfileに以下を記述

FROM nginx:1.19.6
# インクルード用のディレクトリ内を削除
RUN rm -f /etc/nginx/conf.d/*

# Nginxの設定ファイルをコンテナにコピー
COPY ./nginx.conf /etc/nginx/

4. docker/nginx/nginx.confに設定を書きます

user  nginx;
worker_processes  auto;

events {
    worker_connections  1024;
}

http {
    upstream app {
        server unix:///app/tmp/sockets/puma.sock;
    }

    log_format ltsv 'time:$time_iso8601\t'
                    'remote_addr:$remote_addr\t'
                    'request_method:$request_method\t'
                    'request_length:$request_length\t'
                    'request_uri:$request_uri\t'
                    'https:$https\t'
                    'uri:$uri\t'
                    'query_string:$query_string\t'
                    'status:$status\t'
                    'bytes_sent:$bytes_sent\t'
                    'body_bytes_sent:$body_bytes_sent\t'
                    'referer:$http_referer\t'
                    'useragent:$http_user_agent\t'
                    'forwardedfor:$http_x_forwarded_for\t'
                    'request_time:$request_time\t'
                    'upstream_response_time:$upstream_response_time\t'
                    'host:$host';

    server {
        listen 80;
        server_name localhost;

        root /app/public;
        try_files  $uri/index.html $uri @app;

        access_log /var/log/nginx/access.log ltsv;
        error_log /var/log/nginx/error.log;

        location @app {
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_pass http://app;
        }
    }
}

5. config/puma.rbを編集

rails newをしたときにconfig/puma.rbというファイルが作成されています。
puma.rbファイルの一番下に以下のコードを記述します。

# Allow puma to be restarted by `rails restart` command.
plugin :tmp_restart

# ↓これを記述
bind "unix://#{Rails.root}/tmp/sockets/puma.sock"

またpuma.rbの以下の行をコメントアウトします


# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
#
# ↓この行をコメントアウト
- port ENV.fetch("PORT") { 3000 }
+ # port ENV.fetch("PORT") { 3000 }

6. docker-compose.ymlを編集

docker-compose.ymlのapp部分について編集していきます。
1つは、書いてあったここの部分の -b '0.0.0.0'を削除します。

- command: /bin/sh -c "rm -f /app/tmp/pids/server.pid && bundle exec rails s -b '0.0.0.0'"
+ command: /bin/sh -c "rm -f /app/tmp/pids/server.pid && bundle exec rails s"

2つめは、volumesに - tmp-data:/app/tmp/socketsを追加です。

    volumes:
      - .:/app
      - tmp-data:/app/tmp/sockets

3つめは、portsの指定を削除です

    ports:
      - 3000:3000

続いては、nginxについての記述を追加します

  nginx:
    build: ./docker/nginx/
    # Nginxをforegroundで動かすため、daemonをoff
    command: nginx -g 'daemon off;'
    volumes:
      - ./docker/nginx.conf:/etc/nginx/conf.d/default.conf
      - tmp-data:/app/tmp/sockets
    ports:
      - 80:80
    links:
      - app

volumes:
    tmp-data:

上記のコードを追加した結果、docker-compose.yml 全体は今こうなっています

version: "3.7"
services:
  db:
    build: ./docker/mysql/
    environment:
      MYSQL_DATABASE: root
      MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
      TZ: Asia/Tokyo
    expose:
      - 3306
    volumes:
      # 初期データを投入するSQLが格納されているフォルダ
      - ./docker/mysql/mysql_init:/docker-entrypoint-initdb.d
      # 永続化するときにマウントするフォルダ
      - ./docker/mysql/mysql_data:/var/lib/mysql
  app:
    build: .
    command: /bin/sh -c "rm -f /app/tmp/pids/server.pid && bundle exec rails s"
    environment:
      DATABASE_HOST: db
      DATABASE_PORT: 3306
      DATABASE_USER: root
      RAILS_ENV: development
    expose:
      - 3000
    depends_on:
      - db
    #ポート待受していないコンテナがすぐ終了してしまうのを防ぐ
    tty: true
    # コンテナの標準に入力をオープンにする
    stdin_open: true
    volumes:
      - .:/app
      - tmp-data:/app/tmp/sockets

  nginx:
    build: ./docker/nginx/
    # Nginxをforegroundで動かすため、daemonをoff
    command: nginx -g 'daemon off;'
    volumes:
      - ./docker/nginx.conf:/etc/nginx/conf.d/default.conf
      - tmp-data:/app/tmp/sockets
    ports:
      - 80:80
    links:
      - app

volumes:
    tmp-data:

7. Nginx込みでdocker-compose.ymlを立ち上げてみる

docker-compose up --build

起動が確認できたら http:localhost/ にアクセスしてみましょう。:3000 なしのURLにアクセスできたら成功です!

スクリーンショット 2021-01-27 16.50.15.png

Elasticsearchの作成

1. docker/elasticsearch/Dockerfileの作成

mkdir docker/elasticsearch/
touch docker/elasticsearch/Dockerfile

docker/elasticsearch/Dockerfileには以下の記述だけです

FROM elasticsearch:7.10.1

2. elasticsearchをdocker-compose.ymlに追加

  elasticsearch:
    build: ./docker/elasticsearch/
    environment:
      - discovery.type=single-node
      - cluster.name=docker-cluster
      - bootstrap.memory_lock=true
      - ES_JAVA_OPTS=-Xms512m -Xmx512m
    ports:
      - 9200:9200
    volumes:
      - ./docker/elasticsearch/data:/usr/share/elasticsearch/data

3. Dockerを立ち上げて動作確認

docker-compose up

起動が確認できたら http://localhost:9200/ にアクセスしてみましょう。こんな画面が出たら成功です!
スクリーンショット 2021-01-27 17.46.25.png

fluentdの作成

1. docker/fluentd/Dockerfileを作成します

mkdir -p docker/fluentd/
touch docker/fluentd/{Dockerfile,fluent.conf}

docker/fluentd/Dockerfileには以下を記述します。

FROM fluent/fluentd:v1.12-1

USER root
RUN gem install fluent-plugin-elasticsearch

2. docker/fluentd/fluent.confを作成します

以下を記述すればOKです。

<source>
  @type forward
  port 24224
  bind 0.0.0.0
</source>

<filter nginx>
  @type parser
  key_name log
  <parse>
    @type ltsv
  </parse>
</filter>

<match nginx>
  @type elasticsearch
  host elasticsearch
  buffer_type memory
  port 9200
  index_name fluentd
  type_name nginx
  logstash_format true
  logstash_prefix nginx.access
</match>

<filter rails>
  @type parser
  key_name messages
  <parse>
    @type json
  </parse>
</filter>

<match rails>
  @type elasticsearch
  host elasticsearch
  buffer_type memory
  port 9200
  type_name rails
  logstash_format true
  logstash_prefix rails.access
</match>

3. docker-compose.ymlにfluentdを追加

  fluentd:
    build: ./docker/fluentd/
    volumes:
      - ./docker/fluentd/fluent.conf:/fluentd/etc/fluent.conf
    ports:
      - 24224:24224
    depends_on:
      - elasticsearch

続けて既存のdocker-compose.ymlにも編集を加えます

まずはappのdepends_onの箇所に - fluentd を加えます。

  app:
    depends_on:
      - db
      - fluentd # これを追加

次にnginxも編集します。

  nginx:
    build: ./docker/nginx/
    # Nginxをforegroundで動かすため、daemonをoff
    command: nginx -g 'daemon off;'
    volumes:
      - ./docker/nginx.conf:/etc/nginx/conf.d/default.conf
      - tmp-data:/app/tmp/sockets
    ports:
      - 80:80
    links:
      - app
      # ↓ここから下を追加
      - fluentd
    logging: # ロギング(ログ保存)ドライバをfluentdが行う
      driver: fluentd
      options:
        tag: nginx
        # 初期接続をブロックしない
        fluentd-async-connect: "true"

fluentdの設定はこれで完了です。次のKibanaの設定で最後になります!

Kibanaの作成

1. docker/kibana/Dockerfileを作成します

mkdir -p docker/kibana/
touch docker/kibana/Dockerfile

docker/kibana/Dockerfileには以下を記述します。

FROM kibana:7.10.1

2. docker-compose.ymlにkibanaを追加します

  kibana:
    build: ./docker/kibana/
    ports:
      - 5601:5601
    depends_on:
      - elasticsearch

これで完成です!

上記までの記述でdocker-compose.ymlは以下のようになりました

version: "3.7"
services:
  db:
    build: ./docker/mysql/
    environment:
      MYSQL_DATABASE: root
      MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
      TZ: Asia/Tokyo
    expose:
      - 3306
    volumes:
      # 初期データを投入するSQLが格納されているフォルダ
      - ./docker/mysql/mysql_init:/docker-entrypoint-initdb.d
      # 永続化するときにマウントするフォルダ
      - ./docker/mysql/mysql_data:/var/lib/mysql

  app:
    build: .
    command: /bin/sh -c "rm -f /app/tmp/pids/server.pid && bundle exec rails s"
    environment:
      DATABASE_HOST: db
      DATABASE_PORT: 3306
      DATABASE_USER: root
      RAILS_ENV: development
    expose:
      - 3000
    depends_on:
      - db
      - fluentd
    #ポート待受していないコンテナがすぐ終了してしまうのを防ぐ
    tty: true
    # コンテナの標準に入力をオープンにする
    stdin_open: true
    volumes:
      - .:/app
      - tmp-data:/app/tmp/sockets

  nginx:
    build: ./docker/nginx/
    # Nginxをforegroundで動かすため、daemonをoff
    command: nginx -g 'daemon off;'
    volumes:
      - ./docker/nginx.conf:/etc/nginx/conf.d/default.conf
      - tmp-data:/app/tmp/sockets
    ports:
      - 80:80
    links:
      - app
      - fluentd
    logging:
      # ロギング(ログ保存)ドライバをfluentdが行う
      driver: fluentd
      options:
        tag: nginx
        # 初期接続をブロックしない
        fluentd-async-connect: "true"

  elasticsearch:
    build: ./docker/elasticsearch/
    environment:
      - discovery.type=single-node
      - cluster.name=docker-cluster
      - bootstrap.memory_lock=true
      - ES_JAVA_OPTS=-Xms512m -Xmx512m
    ports:
      - 9200:9200
    volumes:
      - ./docker/elasticsearch/data:/usr/share/elasticsearch/data

  fluentd:
    build: ./docker/fluentd/
    volumes:
      - ./docker/fluentd/fluent.conf:/fluentd/etc/fluent.conf
    ports:
      - 24224:24224
    depends_on:
      - elasticsearch

  kibana:
    build: ./docker/kibana/
    ports:
      - 5601:5601
    depends_on:
      - elasticsearch

volumes:
    tmp-data:

ここまでできたら動作確認をしてみましょう。

docker-compose up

Kibanaは http://localhost:5601/app/home/ にアクセスして以下のような画面が表示されたら成功です!

スクリーンショット 2021-01-27 17.44.05.png

KibanaでIndexPatternを作成する

RailsのログをKibanaで見れるようにするためにもう少しだけRailsに手を加えます。

1. gemを追加

Gemfileに以下の2つを追加してください

# Railsのログをfluentdに送る
gem 'act-fluent-logger-rails'
gem 'lograge'

2. config/application.rbに設定追加

  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 6.1

    # ↓これを追加
    # Fluentdのログ設定
    config.log_level = :info
    config.logger = ActFluentLoggerRails::Logger.new
    config.lograge.enabled = true
    config.lograge.formatter = Lograge::Formatters::Json.new
    # ↑ここまで
  end

3. config/fluent-logger.ymlファイルを作成

touch config/fluent-logger.yml

config/fluent-logger.ymlファイルに以下のコードを追記します。

development:
  fluent_host:   fluentd
  fluent_port:   24224
  tag:           'rails'
  messages_type: 'string'

test:
  fluent_host:   '127.0.0.1'
  fluent_port:   24224
  tag:           'rails'
  messages_type: 'string'

production:
  fluent_host:   '127.0.0.1'
  fluent_port:   24224
  tag:           'rails'
  messages_type: 'string'

またRailsのいろいろなログを見るためにscaffoldでCRUD処理を追加しておきます。

docker-compose run app rails g scaffold User name:string
docker-compose run app rails db:migrate

これでRails側の設定は完了です。

再度 docker-compose up --buildをして起動しましょう。

http://localhost/users このページにアクセスしてScaffoleで作られたページが見れたら成功です。

スクリーンショット 2021-01-27 18.30.00.png

IndexPatternを作成

1. kibanaにアクセス

docker-compose up --build

これでKibanaが起動したら
http://localhost:5601/app/management/kibana/indexPatterns/create
にアクセスします。

先程のScaffoldで作られたページ(http://localhost/users )にアクセスをすると、Railsが動くようになり、その結果Kibanaでraisl.access-**というIndex patternを作れるようになります。

スクリーンショット 2021-01-27 18.31.13.png

2. Index pattern nameというテキストフォームに rails.access-*を入力してNext spepに進みます

スクリーンショット 2021-01-27 18.34.11.png

3. Time fieldの値を @timestampにして「Create index pattern」ボタンを押して完成です

スクリーンショット 2021-01-27 18.34.25.png

4. IndexPatterの作成が終わったらログを実際に見てみましょう

http://localhost:5601/app/discover/ にアクセスすると、以下のように直近15分のログが確認できます。

スクリーンショット 2021-01-27 18.37.57.png

これでKibanaでRailsのログを見るための環境をDockerで作ることに成功しました。

おわりに

これでRails×MySQL×Nginx×Fluentd×Elaasticsearch×Kibbanaの環境ができました。

fluentdやKibanaを触ってみることが目的でしたが、Dockerの勉強にもなって楽しかったです。まだ触りたてなので、もっと適切な記述方法などがあればコメントで優しく教えていただけたら幸いです。

参考:https://chulip.org/entry/2019/08/18/233205, https://qiita.com/zgmf_mbfp03/items/0697cc827efa89e5d93e

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?