目的
fluentdやkibanaの使い方を知らなかったので、勉強のために開発環境にDockerでfluentdやkibanaを触れる環境を作ってみました。
この記事のゴールは、fluentdを通してElasticsearchにログを送りKibanaでRailsのログを見ることです。
記事の最後まで進めると、Kibanaでこんな風にRailsのログが表示されます。
概要
フォルダ構成
トップにある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 にアクセスしてみましょう。
この画面が出たら起動成功です!
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にアクセスできたら成功です!
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/ にアクセスしてみましょう。こんな画面が出たら成功です!
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/ にアクセスして以下のような画面が表示されたら成功です!
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で作られたページが見れたら成功です。
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を作れるようになります。
2. Index pattern nameというテキストフォームに rails.access-*
を入力してNext spepに進みます
3. Time fieldの値を @timestamp
にして「Create index pattern」ボタンを押して完成です
4. IndexPatterの作成が終わったらログを実際に見てみましょう
http://localhost:5601/app/discover/ にアクセスすると、以下のように直近15分のログが確認できます。
これで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