In this tutorial, I will show you how to ship your docker containers logs to Grafana Loki via Fluent Bit .
Grafana and Loki
First we need to get Grafana and Loki up and running and we will be using docker and docker-compose to do that.
Our docker-compose-loki.yml
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
version: "3.7"
services:
grafana:
image: grafana/grafana:7.4.2
container_name: 'grafana'
restart: unless-stopped
volumes:
- ./data/grafana/data:/var/lib/grafana
- ./configs/grafana/datasource.yml:/etc/grafana/provisioning/datasources/datasource.yml
networks:
- public
ports:
- 3000:3000
depends_on:
- loki
logging:
driver: "json-file"
options:
max-size: "1m"
loki:
image: grafana/loki:2.1.0
container_name: loki
command: -config.file=/mnt/loki-local-config.yaml
user: root
restart: unless-stopped
volumes:
- ./data/loki/data:/tmp/loki
- ./configs/loki/loki.yml:/mnt/loki-local-config.yaml
ports:
- 3100:3100
networks:
- public
logging:
driver: "json-file"
options:
max-size: "1m"
networks:
public:
name: public
We are referencing 2 config files, first our loki datasource defined by ./configs/grafana/datasource.yml
:
1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: 1
datasources:
- name: loki
type: loki
access: proxy
orgId: 1
url: http://loki:3100
basicAuth: false
isDefault: true
version: 1
editable: true
And our second config is our loki config ./configs/loki/loki.yml
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
auth_enabled: false
server:
http_listen_port: 3100
ingester:
lifecycler:
address: 127.0.0.1
ring:
kvstore:
store: inmemory
replication_factor: 1
final_sleep: 0s
chunk_idle_period: 5m
chunk_retain_period: 30s
max_transfer_retries: 0
schema_config:
configs:
- from: 2018-04-15
store: boltdb
object_store: filesystem
schema: v11
index:
prefix: index_
period: 168h
storage_config:
boltdb:
directory: /tmp/loki/index
filesystem:
directory: /tmp/loki/chunks
limits_config:
enforce_metric_name: false
reject_old_samples: true
reject_old_samples_max_age: 168h
chunk_store_config:
max_look_back_period: 0s
table_manager:
retention_deletes_enabled: false
retention_period: 0s
Once you have everything in place, boot the grafana and loki containers:
1
$ docker-compose -f docker-compose-loki.yml up -d
Fluent Bit
Next we need to boot our log processor and forwarder, fluent bit. In our docker-compose-fluentbit.yml
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
version: "3.7"
services:
fluent-bit:
image: grafana/fluent-bit-plugin-loki:latest
container_name: fluent-bit
environment:
- LOKI_URL=http://loki:3100/loki/api/v1/push
volumes:
- ./fluent-bit.conf:/fluent-bit/etc/fluent-bit.conf
ports:
- "24224:24224"
- "24224:24224/udp"
networks:
- public
networks:
public:
name: public
And as you can see we are referencing a config ./configs/fluentbit/fluent-bit.conf
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[INPUT]
Name forward
Listen 0.0.0.0
Port 24224
[Output]
Name grafana-loki
Match *
Url ${LOKI_URL}
RemoveKeys source,container_id
Labels {job="fluent-bit"}
LabelKeys container_name
BatchWait 1s
BatchSize 1001024
LineFormat json
LogLevel info
Once you have your configs in place, boot fluent-bit:
1
$ docker-compose -f docker-compose-fluentbit.yml up -d
Nginx App
Now to configure our docker container to ship its logs to fluent-bit, which will forward the logs to Loki.
In our docker-compose-app.yml
:
1
2
3
4
5
6
7
8
9
10
11
12
version: "3"
services:
nginx-json:
image: ruanbekker/nginx-demo:json
container_name: nginx-app
ports:
- 8080:80
logging:
driver: fluentd
options:
fluentd-address: 127.0.0.1:24224
The fluent-bit container listens on port 24224 locally on our docker host and is not reachable via its container network, so let’s boot our application:
1
$ docker-compose -f docker-compose-app.yml up -d
Once our application is up, let’s make a request to our nginx-app:
1
2
$ curl http://localhost:8080/
ok
Now head over to Grafana at http://localhost:3000/explore and query: {job="fluent-bit", container_name="/nginx-app"}
and you should see something like this:
Beautiful right? I know.
Github Repo
The source code for this can be found on: