InfluxDB v2 OSS版 (dockerコンテナ) へのマイグレーションの検討

 　現在下記のようなESP気象センサーによる気象データ収集システムを運用しており、気象データ記録用のデータベースとしてDockerコンテナ上で稼働するPostgreSQLとバックアップ用にSQLiteデータベースを使用しています。

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583120/56f55d86-2555-a1ad-bec7-a8e6f7d0372d.jpeg">

#### 想定するデータベースのマイグレーションイメージ

　Dockerコンテナ上で稼働する気象データべース (PostgreSQL) を廃止して、InfluxDB v2 にマイグレーションすることを検討しています。

![Raspi4WeatherMigradeInfluxDB.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583120/d7d8a03b-3140-8c32-acbd-0ba7ef19df96.jpeg)


#### Raspberry Pi で記録しているデータベースの用途
+ Raspberry Pi Zero で収集している気象データベースは主にバックアップ用途
    + Raspberry Pi 4 のメンテナンス作業でデータ収集が中断される場合に対応
    + **他のデータベースへのマイグレーションに使用**
+ Raspberry Pi 4 で収集しているデータベースは可視化アプリ専用

　Dockerイメージを提供しているPostgreSQLなどのデータベースでは、コンテナ生成時にデータベースとテーブルを生成することができますが、**マイグレーションを検討している influxdb v2 (OSS版)でも可能化どうかの検証を行いました**

#### マイグレーションの検証にあたり参考にした記事、書籍

+ [influxdata公式サイト Get started with InfluxDB v2](https://docs.influxdata.com/influxdb/v2/)

+ [RDBエンジニアから見たInfluxDB ― 時系列DBってRDBとはどう違うの? (PDF) **※1系**](
https://www.sraoss.co.jp/wp-content/uploads/files/event_seminar/material/2020/dbts068_session_RDB.pdf)

+ [ネットワークシステムにおけるデータ管理 ～RDBとNoSQL比較～ (前編)](https://www.ntt-tx.co.jp/column/rdbnosql/230323/)

+ [ネットワークシステムにおけるデータ管理 ～RDBとNoSQL比較～ (後編)](https://www.ntt-tx.co.jp/column/rdbnosql/230329/)

+ [InfluxDB v2 のインストールや v1 からの移行について](https://tech.aptpod.co.jp/entry/2022/03/04/130000)

+ インターフェース 2022 年 12 月号「IoT データ・サーバ入門」 [CQ出版社] 
※２年前の発行ですが **v2系**。 からり大掛かりなシステムで説明も図表入でわかりやすくソースコードも提供しており大変参考になりました。
<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583120/d1767814-f22a-613d-047e-66c940dd469e.jpeg">

#### 検証環境

+ OS: Ubuntu 22-04
※本番環境はラズパイ４を想定
+ docker-compose がインストール済み

#### InfluxDB v2 Dockerコンテナ作成で使用したリソース

+ 公式サイトのプログ記事
[Running InfluxDB 2.0 and Telegraf Using Docker](https://www.influxdata.com/blog/running-influxdb-2-0-and-telegraf-using-docker/#docker-compose)

+ Docker compose 設定のリソースファイルがあるGitHubリポジトリ
[GitHub(influxCommunity) InfluxDBv2_Telegraf_Docker](https://github.com/InfluxCommunity/InfluxDBv2_Telegraf_Docker)

以下は上記GitHubリポジトリの Docker compose 設定ファイル

```docker-compose.yml
version: '3'

services:
  influxdb:
    image: influxdb:2.6-alpine
    env_file:
      - influxv2.env
    volumes:
      # Mount for influxdb data directory and configuration
      - influxdbv2:/var/lib/influxdb2:rw
    ports:
      - "8086:8086"
  telegraf:
    image: telegraf:1.25-alpine
    depends_on:
      - influxdb
    volumes:
      # Mount for telegraf config
      - ./telegraf/mytelegraf.conf:/etc/telegraf/telegraf.conf:ro
    env_file:
      - influxv2.env

volumes:
  influxdbv2:
```

+ influxdb v2 の環境設定ファイル
データベースに該当する**バケット(mybucket)はビルド時に生成できるようになっています**

```influxv2.env
DOCKER_INFLUXDB_INIT_MODE=setup
DOCKER_INFLUXDB_INIT_USERNAME=myusername
DOCKER_INFLUXDB_INIT_PASSWORD=passwordpasswordpassword
DOCKER_INFLUXDB_INIT_ORG=myorg
DOCKER_INFLUXDB_INIT_BUCKET=mybucket
DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=mytoken
```

　上記GitHubで公開されているリソースは検証環境でそのままエラーなくビルドが完了しています。※ただしイメージは2024年01月現在の最新
 　**今回はビルド時にスキーマが作成 (テーブルに該当する) できるか検証するためのシェルスクリプトを作成します。**


### ビルド時のスクリプト実行を考慮した構成

#### PostgreSQLの例

　通常 PostgreSQLなどのDockerコンテナではデータベース生成用とテーブル生成の SQLやシェルスクリプトなどを、ビルドエントリーポイントディレクトリにコピーしておくとコンテナビルド時に自動的にデータベースとテープルを生成することができます。

[postgres Docker Official Image: Initialization scripts](https://hub.docker.com/_/postgres)

```
# PostgreSQLコンテナ生成では ホストPC上のディレクトリにDDLを格納する
.
├── .env
├── Dockerfile
├── docker-compose.yml
└── initdb
    ├── 10_createdb_sensors.sql
    └── 11_weather_db.sql
```

Dockerfile の例

```Dockerfile
FROM postgres:12-alpine
# DDLスクリプトを dockerビルドのエントリーポイントにコピー
COPY initdb/*.sql /docker-entrypoint-initdb.d/
```

#### influxdb v2 向け構成例
[influxdb Docker Official Image: Initialization Scripts](https://hub.docker.com/_/influxdb)

コンテナビルド時にスクリプトを実行するカスタム構成


```
.
├── .env                         # 新規作成: 検証環境と本番環境のホストパスを吸収する環境変数
├── Dockerfile                   # 新規作成
├── docker-compose.yml
├── influxv2.env                 # 検証用に編集
├── schema                       # 新規作成
│   └── weather-sensor.json      #   気象データ用のスキーマ定義ファイル
└── scripts                      # 新規作成
    └── create_bucket_schema.sh  #   スキーマ生成シェルスクリプト
```

ホストのボリュームパスとタイムゾーンはこのファイルで設定します

```.env
# データベースボリュームパス
# 本番環境(ラズパイ４)
#HOST_DB_VOLUME=/home/pi/influxdb-v2
# 検証環境(Ubuntu PC)
HOST_DB_VOLUME=/home/yukio/influxdb-v2

# Time zone
TZ=Asia/Tokyo
```

##### タイムゾーン設定有無によるコンテナビルド後のタイムゾーン
(A) タイムゾーン指定無し ※UTCになります
```bash
# ロケール ※ホストのロケールと同一
$ docker exec influxdb echo $LANG
ja_JP.UTF-8
# タイムゾーン
$ docker exec influxdb date +'%Y-%m-%d %H:%M:%S %Z'
2024-01-23 05:29:10 UTC
```
(B) **TZ=Asia/Tokyo** 指定
```bash
$ docker exec influxdb echo $LANG
ja_JP.UTF-8
# タイムゾーン
$ docker exec influxdb date +'%Y-%m-%d %H:%M:%S %Z'
2024-01-23 14:53:40 JST
```

※influxdb内部ではUTCで処理されてます(コンソールログでUTCが確認で きる)、コマンドラインでの管理作業を考慮し私はタイムゾーンをJSTに設定しました。


+ Dockerfileの処理内容
    + イメージは 2024年01月時点の最新
    + ビルド時に実行するシェルスクリプトをエントリーポイントにコピー
    + コンテナにスキーマディレクトリを作成
    + コンテナのスキーマディレクトリに初期化スキーマをコピー
```Dockerfile
FROM influxdb:2.7-alpine

COPY scripts/*.sh /docker-entrypoint-initdb.d/
RUN mkdir -p /var/lib/influxdb2/schema
COPY schema/*.json /var/lib/influxdb2/schema
```

[変更点] ホスト側のデータベース保存ディレクトリを指定

Telegraf のイメージは 2024年01月時点の最新

```docker-compose.yml
version: '3'

services:
  influxdb:
    build: .
    container_name: influxdb
    env_file:
      - influxv2.env
      - ./.env
    volumes:
      # Mount for influxdb data directory and configuration
      - influxdbv2:/var/lib/influxdb2:rw
    ports:
      - "8086:8086"
  telegraf:
    image: telegraf:1.29-alpine
    depends_on:
      - influxdb
    volumes:
      # Mount for telegraf config
      - ./telegraf/mytelegraf.conf:/etc/telegraf/telegraf.conf:ro
    env_file:
      - influxv2.env

volumes:
  influxdbv2:
    driver: local
    driver_opts:
      type: "none"
      device: ${HOST_DB_VOLUME}
      o: bind
```

[influxdb環境変数] 本番環境 (ラズパイ) を想定した値に変更

```influxv2.env
DOCKER_INFLUXDB_INIT_MODE=setup
DOCKER_INFLUXDB_INIT_USERNAME=developer
DOCKER_INFLUXDB_INIT_PASSWORD=[YOUR DEVELOPER PASSWORD]
DOCKER_INFLUXDB_INIT_ORG=raspi-influxdb
DOCKER_INFLUXDB_INIT_BUCKET=sensor-bucket
DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=9jTPSRXyl3345awX
```

+ [参考] トークンの生成方法
[How to Generate a Random String in Linux?](https://itslinuxfoss.com/generate-random-string-linux/)

```bash
$ openssl rand -base64 12
9jTPSRXyl3345awX
```


+ スキーマ定義ファイル作成で参考にした公式ドキュメント
[Manage bucket schemas](https://docs.influxdata.com/influxdb/cloud/admin/buckets/bucket-schema/?t=usage-cpu.json)

```weather_sensor.json
[
  {"name": "time", "type": "timestamp"},
  {"name": "did", "type": "tag"},
  {"name": "temp_out", "type": "field", "dataType": "float"},
  {"name": "temp_in", "type": "field", "dataType": "float"},
  {"name": "humid", "type": "field", "dataType": "float"},
  {"name": "pressure", "type": "field", "dataType": "float"}
]
```

+ スキーマ生成シェルスクリプト
    + --bucket **sensor-bucket** ※データベース名に相当
    + --name **weather** ※テーブル名に相当
    + コンテナ内のスキーマ定義ファイルへの絶対パス  
[influx bucket-schema create](https://docs.influxdata.com/influxdb/v2/reference/cli/influx/bucket-schema/create/)

```create_bucket_schema.sh
#!/bin/bash

influx bucket-schema create \
  --bucket sensor-bucket \
  --name weather \
  --columns-file /var/lib/influxdb2/schema/weather-sensor.json
```

### docker-compose ビルドと起動

```bash
$ cd ~/docker/influxdb/v2
$ docker-compose up --build
```

以下はエラーが発生するまでのログですが一部省略しています。

```bash
Creating network "v2_default" with the default driver
Building influxdb
[+] Building 30.8s (9/9) FINISHED                                                                                            docker:default
 => [internal]
 load .dockerignore                                             0.8s
 => => transferring context: 2B                                 0.0s
 => [internal] load build definition from Dockerfile            0.9s
 => => transferring dockerfile: 196B                            0.0s
 => [internal] load metadata for docker.io/library/influxdb:2.7-alpine                                                                 2.2s
 => [1/4] FROM docker.io/library/influxdb:2.7-alpine@sha256:2ec0745cc2eed5444c599e274e59580162c840f43d917a493cab07ee9d41f746          18.9s
# ...一部省略...
 => [2/4] COPY scripts/*.sh /docker-entrypoint-initdb.d/         3.5s
 => [3/4] RUN mkdir -p /var/lib/influxdb2/schema                 1.7s
 => [4/4] COPY schema/*.json /var/lib/influxdb2/schema           1.4s
 => exporting to image                                           1.1s
 => => exporting layers                                          1.0s
 => => writing image sha256:37e464a289803384230746f5092c3d9f7d9d0adc06edd575bcf4fa350b5d321d                                           0.0s
 => => naming to docker.io/library/v2_influxdb                                                                                         0.1s
Pulling telegraf (telegraf:1.29-alpine)...
1.29-alpine: Pulling from library/telegraf
# ...一部省略...
Status: Downloaded newer image for telegraf:1.29-alpine
Creating influxdb ... done
Creating v2_telegraf_1 ... done
Attaching to influxdb, v2_telegraf_1
influxdb    | {
influxdb    |   "bolt-path": "/var/lib/influxdb2/influxd.bolt",
influxdb    |   "engine-path": "/var/lib/influxdb2/engine",
influxdb    |   "nats-port": 4222,
influxdb    |   "http-bind-address": ":9999"
influxdb    | }
influxdb    | 2024-01-16T10:44:19.	info	booting influxd server in the background	{"system": "docker"}
# ...一部省略...
influxdb    | User		Organization	Bucket
influxdb    | developer	raspi-influxdb	sensor-bucket
influxdb    | 2024-01-16T10:51:25.	info	Executing user-provided scripts	{"system": "docker", "script_dir": "/docker-entrypoint-initdb.d"}
influxdb    | /docker-entrypoint-initdb.d/create_bucket_schema.sh:
influxdb    | Error: InfluxDB Cloud-only command used with InfluxDB OSS host
influxdb    | run-parts: /docker-entrypoint-initdb.d/create_bucket_schema.sh exited with return code 1
```

スキーマ生成シェルスクリプト実行時のエラーメッセージ 

```
Error: InfluxDB Cloud-only command used with InfluxDB OSS host
```
※ビルド後のコンテナ起動時にエラーが発生したのでコンテナは起動しませんでした。


#### 公式サイトの説明

　Google翻訳で日本語に翻訳すると**OSS v2.3では利用不可**と私は読み取れましたが、 **OSS v2.3未満ではどうなんだろうと思い 相当古い v2 (2.1-alpne) のイメージでもビルドしてみましたが結果は変わりませんでした。※エラー内容は若干異なっていますが**

```bash
Error: failed to create measurement: InfluxDB Cloud-only command failed: 404 Not Found
```

>**influx CLI 2.1.0+　　InfluxDB Cloud only**

>### Works with InfluxDB Cloud bucket schemas
> influx bucket-schema and its subcommands work with InfluxDB Cloud bucket schemas. **This feature is not available in InfluxDB OSS v2.3.**

OSS版は提供しないとはっきり書いてくれれば納得なんですがね。

　下記に SQLiteデータベース (2年分約11万件) をinfluxdb v2 にマイグレーションする方法を公開しました。

[InfluxDB v2 (OSS版) SQLite3データベースのマイグレーション (Qiita@pipito-yukio)](https://qiita.com/pipito-yukio/items/3f9b0e58969ef588082f)