はじめに
Docker ロギング・ドライバを使ってコンテナログを ELK スタックで利用する – oki2a24 の続きです。
前回は、 1 つの Docker Compose に、 アプリ (Nginx) も Logstash も Elasticsearch も Kibana も全部入っていました。
開発環境ではこれで足ります。けれども、他のアプリのログも集めたいとなりますと、 Elasticsearch と Kibana は独立させたいと思うようになりました。
今回、以下の 2 つの Docker Compose を用意し、これらを Docker のネットワークで繋ぐことで ELK スタックを実現できましたので、ノートいたします。
- Docker Compose その 1: Nginx と Logstash
- Docker Compose その 2: Elasticsearch と Kibana
ポイント
- "Docker Compose その 2: Elasticsearch と Kibana" を最初に起動し、次に、 "Docker Compose その 1: Nginx と Logstash" を起動しなければならない。逆にすると、 "その 1" でログ出力しても "その 2" が立ち上がっていないので受け取れない。それにそもそも、 "その 1" 起動時に、エラーになるようにした。
- "その 2" 起動時に、他の Docker Compose から接続できるように名前付きのネットワークを作成するようにした。これを行わない場合、別途 Dokcer ネットワークを作成しておく必要があるので、面倒。
- "その 2" の docker-compose.yml でトップレベルの networks で name オプションを指定したネットワークを作成する。そのためには、 Docker Compose のバージョンを、 3.5 とする必要がある。なお、他の Docker Compose のバージョンは 3 でも問題なかった。
- "その 1" から "その 2" に接続するには、
- "その 1" の docker-compose.yml でトップレベル の networks 設定で外部ネットワークを指定し、接続したい services での networks でも外部ネットワークを指定する必要がある。
コード
ディレクトリ構成
$ tree
.
├── app1
│ ├── docker-compose.yml
│ └── logstash
│ └── pipeline
│ └── logstash.conf
└── es
└── docker-compose.yml
4 directories, 3 files
$
Docker Compose その 1: Nginx と Logstash
ディレクトリ構成での app1
に当たります。
- トップレベルの networks で外部の Docker ネットワークの es_net を指定。ちなみに、 es_net が存在していなければ、エラーとなる。
- services の logstash の networks で、 es_net を指定。これによって、 logstash の output は es_net へと流れるようになる。
app1/docker-compose.yml
version: "3"
services:
logstash:
image: docker.elastic.co/logstash/logstash-oss:7.0.1
ports:
- "12201:12201/udp"
volumes:
- "./logstash/pipeline:/usr/share/logstash/pipeline"
networks:
- es_net
nginx:
image: nginx:latest
ports:
- "80:80"
logging:
driver: gelf
options:
gelf-address: udp://localhost:12201
tag: "docker.{{.Name}}"
depends_on:
- logstash
networks:
es_net:
external: true
次のファイルは前回と同じです。
app1/logstash/pipeline/logstash.conf
input {
gelf {
type => docker
port => 12201
}
}
filter {
grok {
match => { "message" => ["%{IPORHOST:[nginx][access][remote_ip]} - %{DATA:[nginx][access][user_name]} \[%{HTTPDATE:[nginx][access][time]}\] \"%{WORD:[nginx][access][method]} %{DATA:[nginx][access][url]} HTTP/%{NUMBER:[nginx][access][http_version]}\" %{NUMBER:[nginx][access][response_code]} %{NUMBER:[nginx][access][body_sent][bytes]} \"%{DATA:[nginx][access][referrer]}\" \"%{DATA:[nginx][access][agent]}\""] }
remove_field => "message"
}
mutate {
add_field => { "read_timestamp" => "%{@timestamp}" }
}
date {
match => [ "[nginx][access][time]", "dd/MMM/YYYY:H:m:s Z" ]
remove_field => "[nginx][access][time]"
}
useragent {
source => "[nginx][access][agent]"
target => "[nginx][access][user_agent]"
remove_field => "[nginx][access][agent]"
}
geoip {
source => "[nginx][access][remote_ip]"
target => "[nginx][access][geoip]"
}
}
output {
elasticsearch {
hosts => [ 'elasticsearch' ]
index => "access_log1"
}
}
Docker Compose その 2: Elasticsearch と Kibana
ディレクトリ構成での es
に当たります。
- フォーマットの version は 3.5 を指定する。そうしないと、 networks の name オプションが使えない。
- トップレベルの networks で、 name オプションで名前をつけておく。これによって、
docker compose up
すると同時に、 name オプションで指定した名前で Docker ネットワークが作成される。この名前で、他の Dokcer Compose からアクセスできるようになる。
es/docker-compose.yml
version: "3.5"
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.0.1
ports:
- "9200:9200"
- "9300:9300"
environment:
discovery.type: "single-node"
volumes:
- "es_data:/usr/share/elasticsearch/data"
kibana:
image: docker.elastic.co/kibana/kibana-oss:7.0.1
ports:
- "5601:5601"
environment:
ELASTICSEARCH_URL: "http://elasticsearch:9200"
depends_on:
- elasticsearch
volumes:
es_data:
driver: local
networks:
default:
name: es_net
確認
cd es/
docker-compose up -d
cd ../app1/
docker-compose up -d
その後、
http://localhost/
にアクセスして Nginx ウェルカムページを確認する。http://localhost:9200/_cat/indices?v
にアクセスして、 Elasticsearch にindex
がaccess_log1
のデータができているかを確認する。http://localhost:5601/app/kibana#/dev_tools/console?_g=()
にアクセスし、 Console でGET /access_log1/_search?pretty=true
を実行して、 Nginx のログが出力されることを確認する。
となりましたので、 OK です。やったぜ!!!
おわりに
実は、この後で詰まっています。
複数の Docker コンテナからそれぞれ異なる index で "その 2" の Elasticsearch へとログを送ったのですけれども、 2 つ目の index を送った時点で Elasticsearch コンテナが Exit してしまいます。
これでは、実用になりません。色々いじくる、そしてそもそも Elasticsearch そのものについてお勉強する、ということが必要になってきたと感じます。
詰まっていますけれども、その前に、一つ前回の投稿からはステップアップできましたので、今回投稿いたしました。
次のページが参考になりました。ありがとうございます?。
- 日本語の Docker ネットワーク設定リファレンス
以上です。