UbuntuのechoをFluentdで捕捉する（docker-compose.ymlサンプルあり）

## はじめに

[前回記事](https://qiita.com/t13801206/items/d67769655fb685953eb1)では、fluentdの`docker compose`のサンプルを試した
HTTPアクセスのログをブラウザ（kibana）でグラフィカルに見ることができた

---

今回は、１つ立ち戻り[Docker Logging Driver](https://docs.fluentd.org/container-deployment/docker-logging-driver)を試す

サンプルをコピペすれば動くことは自明（？）なので
`docker-compose.yml`ファイルにubuntuとfluentdをまとめて定義し
さらにdockerネットワークにそれらを所属させて
ubuntuのechoをfluentdに流し込むことを行う

:::note warn
実際には、公式サンプルのままでは指定しているバージョンが古かったりして動かないこともある
:::

## fluentd/Dockerfile

公式サンプルとほぼ同じ
バージョンは`5.2.4`に上げている

```dockerfile
# fluentd/Dockerfile

FROM fluent/fluentd:v1.12.0-debian-1.0
USER root
RUN ["gem", "install", "fluent-plugin-elasticsearch", "--no-document", "--version", "5.2.4"]
USER fluent
```

### fluent.conf

コンフィグファイルはサンプルのまま
どこも変更していない

```xml
<source>
  @type forward
  port 24224
  bind 0.0.0.0
</source>

<match *>
  @type stdout
</match>
```

24224ポートで受けた内容を標準出力する

## docker-compose.yml

まずは完成形

```yml
version: "3"
services:
  fluentd:
    build: ./fluentd
    volumes:
      - ./fluentd/conf:/fluentd/etc
    ports:
      - "24224:24224"
      - "24224:24224/udp"
    networks:
      efk-net:
        ipv4_address: 172.22.0.10
  
  client1:
    image: ubuntu
    tty: true
    stdin_open: true
    networks:
      - efk-net
    depends_on:
      - fluentd
    logging:
      driver: "fluentd"
      options:
        fluentd-address: 172.22.0.10:24224
        fluentd-async-connect: "true"
        fluentd-retry-wait: 2s
        fluentd-max-retries: 30

networks:
  efk-net:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.22.0.0/16
```

ymlファイルの全体像は以上

### fluentdのポイント

dockerネットワークに所属する他のコンテナからみたときに
IPアドレスがわかっているほうが都合がよいので
IPアドレスを固定しておく

```yml
    networks:
      efk-net:
        ipv4_address: 172.22.0.10
```

### ubuntuのポイント

ロギングは fluentd を指定する
先ほど固定したIPアドレスと、コンフィグファイルで指定したポートがアドレスとなる

```yml
    logging:
      driver: "fluentd"
      options:
        fluentd-address: 172.22.0.10:24224
        fluentd-async-connect: "true"
        fluentd-retry-wait: 2s
        fluentd-max-retries: 30
```

fluentdコンテナが起動するまえにubuntuが立ち上がるとエラーが出る

＜エラーメッセージ＞

> Error response from daemon: failed to initialize logging driver: dial tcp 172.20.10.4:24224: connect: connection refused.

エラーを回避するために、非同期でfluentdに接続するよう設定する

```json
fluentd-async-connect: "true"
```

参考：[My web server tries to connect to fluentd before listening port on docker](https://stackoverflow.com/questions/71933584/my-web-server-tries-to-connect-to-fluentd-before-listening-port-on-docker)

## コンテナを起動する

コンテナをバックグラウンドで起動する
`docker-compose.yml`ファイルが存在する階層で以下のコマンドを実行する

```powershell
docker compose up -d
```

コンテナのログを画面に表示する

```powershell
docker compose logs -f
```

ログ表示を中止するときは`Ctrl + C`

## Ubuntuからechoする

Ubuntuコンテナに入る

```powershell
docker compose exec client1 bash
```

単純にechoするだけではfluentdのログに表示されない

なぜログがfluentdに流れないのか？

[docker container内で叩いたコマンドを docker log に出力する方法](https://qiita.com/uturned0/items/2404aa8233cbf2b276f8)
こちらの記事がとても分かりやすい

### 結論

> つまり、コンテナ内で実行したコマンド結果を /proc/1/fd/1 に流せば docker logとして扱われます。

とのことらしい。
PID=1かつファイルディスクリプタ(fd)=1(標準出力)
に対してecho結果をリダイレクトすると
Dockerログとなり、Fluentdに流れる

```bash
echo "Hello, Fluentd" > /proc/1/fd/1
```

＜dockerのログ＞

```bash
2306_fluentdstudy-client1-1  | Hello, Flunetd
2306_fluentdstudy-fluentd-1  | 2023-06-14 12:28:57.000000000 +0000 91cecac07bb7: {"source":"stdout","log":"Hello, Flunetd\r","container_id":"91cecac07bb70f4455d33cab12791c930aaa2b064680002ae0e62b254c01b66d","container_name":"/2306_fluentdstudy-client1-1"}
```

## おわりに

ubuntuコンテナのログをfluentdコンテナの標準出力に表示させた
公式のサンプルでは docker run までしか載っていないが
今回はdocker-compose.ymlにまとめて、１コマンドで環境をつくれるようにした

単純な echo では、ubuntuのログがfluentdに流れなかったが
`echo "Hello, Fluentd" > /proc/1/fd/1`とすることで
ubuntuのログがfluentdの標準出力に表示されるようになった

以上

今後は、単なるechoではなく、syslogをfluentdに渡したい

## 参考

https://milestone-of-se.nesuke.com/sv-basic/linux-basic/fd-stdinout-pipe-redirect/

## 糸冬了！！