Help us understand the problem. What is going on with this article?

Dockerで、DatabaseからElasticsearchにLogstashを使ってデータを流してみた

More than 1 year has passed since last update.

こんにちは。
Web・iOSエンジニアの三浦です。

今回は、DatabaseからElasticsearchへ、Logstashを使ってデータを流す処理をDocker上で実現してみました。

ちなみに今回説明するコードは、以下のgithubで公開しています。
https://github.com/takayuki-miura0203/docker-elastic-sample

準備

環境

Dockerが実行できる環境であれば大丈夫です。

実装してみる

Elasticsearch

Databaseからデータを移す先です。

Dockerfile

Dockerfileでは、公式のイメージを入れるだけです。

FROM docker.elastic.co/elasticsearch/elasticsearch:7.3.0

docker-compose.yml

テストのため、シングルノードで実行します。

elasticsearch:
  build: ./elasticsearch
  container_name: elasticsearch
  environment:
    discovery.type: single-node
  ports:
    - 9200:9200
    - 9300:9300

Kibana

データの確認などをするため、Kibanaも入れます。

Dockerfile

こちらも、Dockerfileでは公式のイメージを入れるだけです。

FROM docker.elastic.co/kibana/kibana:7.3.0

docker-compose.yml

Kibanaに関しては、 docker-compose.yml でも特別なことはしません。

kibana:
  build: ./kibana
  container_name: kibana
  ports:
    - 5601:5601

MySQL

Elasticsearchへ移すデータを入れます。

Dockerfile

今回は初期データを入れたいため、MySQLが公式で提供しているサンプルデータである world.sql の入った initdb.d ディレクトリを、 /docker-entrypoint-initdb.d ディレクトリとしてコピーするようにします。
DockerのMySQLは、 /docker-entrypoint-initdb.d に入っているsqlファイルを起動時に実行してくれます。

FROM mysql:8.0.17

COPY ./initdb.d /docker-entrypoint-initdb.d

https://github.com/takayuki-miura0203/docker-elastic-sample/tree/master/mysql/initdb.d

docker-compose.yml

ROOTユーザのパスワードを適当に決め、TZも一応入れておきます。

mysql:
  build: ./mysql
  container_name: mysql
  environment:
    MYSQL_ROOT_PASSWORD: root
    TZ: 'Asia/Tokyo'
  ports:
    - 3306:3306
    - 33060:33060

Logstash

DatabaseからElasticsearchへデータを移すアプリケーションです。

Dockerfile

公式イメージの pull に加え、データを移す処理を書いた設定ファイルを内包する pipeline ディレクトリを所定のディレクトリにコピーします。
この際、PCが重くなる対策として、デフォルトで存在した設定ファイルは削除しておきます。
また今回はDBからデータを取得するため、必要となるJDBCライブラリ( mysql-connector-java-8.0.17.jar )も公式サイトからダウンロードしておき、イメージにコピーします。
なお、どうやらJDK11への対応の関係でJDBCがうまく動かないようなので、Logstashは最新版ではなく少し昔のものを使っています。

FROM docker.elastic.co/logstash/logstash:6.8.2

RUN rm -rf /usr/share/logstash/pipeline
COPY pipeline /usr/share/logstash/pipeline
COPY mysql-connector-java-8.0.17.jar /usr/share/logstash/mysql-connector-java-8.0.17.jar

pipeline

データを移す処理に関しては、今回はシンプルにDBの指定テーブルのデータをElasticsearchへ移すだけの処理を書きました。
なおElasticsearchのホストは、Dockerで名前を指定している elasticsearch です。

input {
  jdbc {
    jdbc_driver_library => "/usr/share/logstash/mysql-connector-java-8.0.17.jar"
    jdbc_driver_class => "com.mysql.cj.jdbc.Driver"
    jdbc_connection_string => "jdbc:mysql://mysql:3306/world"
    jdbc_default_timezone => "Asia/Tokyo"
    jdbc_user => "root"
    jdbc_password => "root"
    jdbc_default_timezone => "Asia/Tokyo"
    statement => "SELECT * FROM city"
  }
}

output {
  elasticsearch {
    hosts => ["elasticsearch"]
    index => "city"
  }
}

https://github.com/takayuki-miura0203/docker-elastic-sample/tree/master/logstash/pipeline

docker-compose.yml

docker-compose.yml では、特別なことは何もしません。

logstash:
  build: ./logstash
  container_name: logstash
ports:
  - 5044:5044
  - 9600:9600

実行!

コンテナ起動・実行

今回は実行も簡単にできるよう Makefile を作ってみました。

.PHONY: start
start:
    docker-compose up --build

.PHONY: prune
prune:
    docker system prune -a --volumes

以下からコンテナの起動・処理の実行ができます。

make start

結果を見てみる

Kibana上で、以下のようにデータが入っていることが確認できました!

{
  "took" : 836,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4079,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "city",
        "_type" : "_doc",
        "_id" : "tB1NhmwB5V7ePKeX7Lgo",
        "_score" : 1.0,
        "_source" : {
          "@version" : "1",
          "countrycode" : "BRA",
          "district" : "Rio de Janeiro",
          "@timestamp" : "2019-08-12T14:48:57.725Z",
          "name" : "Macaé",
          "id" : 376,
          "population" : 125597
        }
      },
      {
        "_index" : "city",
        "_type" : "_doc",
        "_id" : "tR1NhmwB5V7ePKeX7Lgp",
        "_score" : 1.0,
        "_source" : {
          "@version" : "1",
          "countrycode" : "BRA",
          "district" : "Minas Gerais",
          "@timestamp" : "2019-08-12T14:48:57.725Z",
          "name" : "Teófilo Otoni",
          "id" : 377,
          "population" : 124489
        }
      },
      {
        "_index" : "city",
        "_type" : "_doc",
        "_id" : "th1NhmwB5V7ePKeX7Lgq",
        "_score" : 1.0,
        "_source" : {
          "@version" : "1",
          "countrycode" : "BRA",
          "district" : "São Paulo",
          "@timestamp" : "2019-08-12T14:48:57.725Z",
          "name" : "Moji-Guaçu",
          "id" : 378,
          "population" : 123782
        }
      },
      {
        "_index" : "city",
        "_type" : "_doc",
        "_id" : "tx1NhmwB5V7ePKeX7Lgq",
        "_score" : 1.0,
        "_source" : {
          "@version" : "1",
          "countrycode" : "BRA",
          "district" : "Tocantins",
          "@timestamp" : "2019-08-12T14:48:57.725Z",
          "name" : "Palmas",
          "id" : 379,
          "population" : 121919
        }
      },
      {
        "_index" : "city",
        "_type" : "_doc",
        "_id" : "uB1NhmwB5V7ePKeX7Lgq",
        "_score" : 1.0,
        "_source" : {
          "@version" : "1",
          "countrycode" : "BRA",
          "district" : "São Paulo",
          "@timestamp" : "2019-08-12T14:48:57.725Z",
          "name" : "Pindamonhangaba",
          "id" : 380,
          "population" : 121904
        }
      }
    ]
  }
}

さいごに

Elasticsearch、Kibana、MySQL、Databaseという、それだけ聞くとなかなかに実装が重そうな内容でしたが、やってみたら案外あっさりできました(typoに気づかず悩んだりはしましたが…w)。
Production用に作ったわけではないので色々と簡素ですが、これなら今後Dockerで色々と遊べそうです。

なおこれを動かすと処理の負荷が結構大きいので、PCが重くなったりなどは注意が必要です。

参考文献

以下のサイトを参考にさせていただきました。
ありがとうございました!

https://catalina1344.hatenablog.jp/entry/2019/01/20/170821
https://www.elastic.co/guide/en/elasticsearch/reference/7.3/docker.html#_pulling_the_image
https://www.elastic.co/guide/en/logstash/current/docker.html
https://www.elastic.co/guide/en/kibana/current/docker.html
https://qiita.com/sugikeitter/items/f3b2c57bf8bbdc47a8bc
https://qiita.com/shione/items/dfa956a47b6632d8b3b3
https://qiita.com/astrsk_hori/items/e3d6c237d68be1a6f548
https://budougumi0617.github.io/2018/05/20/create-instant-mysql-by-docker/
https://qiita.com/A-Kira/items/f401aea261693c395966
https://qiita.com/S-T/items/923cf689ee5f44525457
https://qiita.com/NagaokaKenichi/items/ae037963b33a85df33f5
https://github.com/dimMaryanto93/docker-logstash-input-jdbc-plugin-mysql

takayuki-miura0203
エンジニア。Webのフロントエンド(es5, es6など) ~ バックエンド(主にPHP)、iOSアプリ(Swift)とかやってます。 最近はAWSなども。 Twitterはこちら https://twitter.com/miura0203
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした