ローカルコンテナの出力をFluentdでS3に保存する

# やりたいこと
ローカルでFluentdコンテナを動かして、他のコンテナの標準出力を集めてS3にログを保存したい。

# 構成
Fluentdコンテナと、サンプルとしてそこに出力を送り込むNginxコンテナを作ります。

```
├─fluentd
│      docker-compose.yml
│      Dockerfile
│      fluent.conf
│
└─nginx
        docker-compose.yml
```

# Fluentdコンテナ

```dockerfile:Dockerfile
FROM fluent/fluentd:v1.12.2-1.0

# Timezone
ARG TZ
RUN echo ${TZ}

USER root
RUN apk add --update --no-cache tzdata && \
    cp /usr/share/zoneinfo/${TZ} /etc/localtime && \
    echo ${TZ} > /etc/timezone && \
    apk del tzdata

# AWS
ARG AWS_KEY_ID
ARG AWS_SEC_KEY
ARG S3_BUCKET
ARG AWS_REGION
ENV AWS_KEY_ID=${AWS_KEY_ID}
ENV AWS_SEC_KEY=${AWS_SEC_KEY}
ENV S3_BUCKET=${S3_BUCKET}
ENV AWS_REGION=${AWS_REGION}
# for fluentd v1.0 or later
RUN gem install fluent-plugin-s3 --no-document

# Config
USER fluent
COPY fluent.conf /fluentd/etc/
```

デフォルトだとログのタイムスタンプがUTCになってしまうのでタイムゾーンの設定と、S3出力のためのプラグインをインストールします。

```yaml:docker-compose.yml
version: '3.7'

services:
  fluentd:
    build:
      context: ./
      args:
        TZ: Asia/Tokyo
        AWS_KEY_ID: XXXXXXXXXXXXXXXX
        AWS_SEC_KEY: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        S3_BUCKET: mybucket
        AWS_REGION: ap-northeast-1
    restart: always
    ports:
      - 24224:24224
      - 24224:24224/udp
```
タイムゾーンとAWSのアクセスキーと出力先のバケットを渡します。

```fluent.conf
<source>
  @type forward
  port 24224
  bind 0.0.0.0
</source>

<match debug.**>
  @type copy

  <store>
    @type file
    path /fluentd/log/debug
    time_slice_format %Y%m%dT%H%M
    time_slice_wait 5m
  </store>

  <store>
    @type stdout
  </store>
</match>

<match s3.**>
  @type s3
  aws_key_id "#{ENV['AWS_KEY_ID']}"
  aws_sec_key "#{ENV['AWS_SEC_KEY']}"
  s3_bucket "#{ENV['S3_BUCKET']}"
  s3_region "#{ENV['AWS_REGION']}"
  check_object false
  time_slice_format %Y%m%dT%H%M
  time_slice_wait 5m
  path fluentd_logs/
  s3_object_key_format %{path}%{time_slice}/%{hms_slice}.%{file_extension}
</match>

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

`s3.**`タグにマッチした入力がS3に保存されるように設定します。
確認用に保存のタイミングを短くしています。

## コンテナの起動・確認

Fluentdコンテナを起動して、直接データを入力してみます。

```
>docker-compose up -d
>docker-compose exec fluentd sh

$ echo '{"hello":"fluentd"}' | fluent-cat debug.test
$ ls -l /fluentd/log/debug/
-rw-r--r--    1 fluent   nogroup         57 Apr 28 14:00 buffer.b5c1014353321a2e64426684b2464c202.log
-rw-r--r--    1 fluent   nogroup         79 Apr 28 14:00 buffer.b5c1014353321a2e64426684b2464c202.log.meta
$ ls -l /fluentd/log/
drwxr-xr-x    2 fluent   nogroup       4096 Apr 28 14:07 debug
-rw-r--r--    1 fluent   nogroup         57 Apr 28 14:04 debug.20210428T1400.log
$ cat /fluentd/log/debug.20210428T1400.log
2021-04-28T14:00:52+09:00       debug.test      {"hello":"fluentd"}

$ echo '{"hello":"fluentd"}' | fluent-cat s3.test

>aws s3 ls s3://mybucket/fluentd_logs/
                           PRE 20210428T1400/
```

コンテナ内部とS3にログが保存されることが確認できました。
S3にはgzip形式でログが保存されます。

# Nginxコンテナ

```yaml:docker-compose.yml
version: '3.7'

services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
    logging:
      driver: "fluentd"
      options:
        fluentd-address: "localhost:24224"
        tag: "s3.docker.{{.Name}}"
        fluentd-async-connect: "true"
```

Nginxの公式イメージはデフォルトでアクセスログを標準出力にエラーログを標準エラー出力に吐くのでロギング・ドライバにFluentdを指定すればそのままログが流れます。

コンテナを起動して、NginxデフォルトページにアクセスするとS3にアクセスログが保存されているのが確認できます。

```
2021-04-28T14:55:31+09:00	s3.docker.nginx_web_1	{"source":"stdout","log":"172.23.0.1 - - [28/Apr/2021:05:55:31 +0000] \"GET / HTTP/1.1\" 200 612 \"-\" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36\" \"-\"","container_id":"410c2125509ef500c8a22a3093c95ac1b9ee51d9ff893a4d062f7bb7fb56a8c9","container_name":"/nginx_web_1"}
```