こんにちは。
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
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"
}
}
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