4 minutes
litestream / minio を docker compose で試す
お世話になっております。
しゃまとんです😊
最近 litestream というソフトウェアが話題(?)ですね。
Go 周辺の界隈の方々だと、そんな流れがきていたのを目にされていたのではないでしょうか。
LiteStream、go-sqlite3 が使われていた。
— mattn (@mattn_jp) May 6, 2022
I'm All-In on Server-Side SQLite · Fly https://t.co/xgpo9aEul6 "今はhttps://t.co/Wvex0NIBimでLitestreamの開発をしています" Litestream の作者 Fly\.io で Litestream 開発するのが仕事になってるのか。素敵すぎるな。
— V (@voluntas) May 10, 2022
ということで、なぜか私も琴線に触れたので N 番煎じとなりそうではありますが litestream を試してみました。私もケチケチ星人なので手元で minio を使ってやって行きたいと思います。
litestream + minio の初手については公式とかこの辺が参考になります。
今回の検証リポジトリは shamaton/litestream-sample にありますので、適宜持ってきてくださいませ。
事前準備
local で litestream から minio に連携するには、 https でのアクセスが必要です。 そのため、証明書まわりを適当に作成しておきます。証明書の細かい入力は空 Enter でOKです。(OpenSSL でないとうまくいかないかも)
# make setup
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./tmp/certs/private.key -out ./tmp/certs/public.crt
docker-compose.yml
docker-compose.yml はこのようにしました。
version: '3'
services:
# s3
minio:
image: minio/minio:RELEASE.2022-05-08T23-50-31Z
environment:
MINIO_ROOT_USER: "user"
MINIO_ROOT_PASSWORD: "password"
command: server /data --console-address :9001
volumes:
- ./tmp/minio:/data:cached
- ./tmp/certs:/root/.minio/certs
ports:
- "9000:9000"
- "9001:9001"
# bucket creator
minio-client:
image: minio/mc:RELEASE.2022-05-09T04-08-26Z
depends_on:
- minio
entrypoint: >
/bin/sh -c " until (/usr/bin/mc config host add --insecure myminio https://minio:9000 user password) do echo '...waiting...' && sleep 1; done; /usr/bin/mc mb --insecure myminio/mybucket; exit 0; "
# try to restore database
litestream-restore:
image: litestream/litestream:sha-10e25d7c9eb2524254ad533d9bf55a50ec5ac4d7
entrypoint: /bin/sh
command: -c "rm -rf /data/*; litestream restore /data/db.sqlite; exit 0;"
volumes:
- ./tmp/sqlite:/data
- ./litestream.yml:/etc/litestream.yml:ro
depends_on:
minio-client:
condition: service_completed_successfully
# my application
app:
build:
context: .
volumes:
- ./tmp/sqlite:/data
ports:
- "3000:3000"
healthcheck:
test: curl -s http://localhost:3000/health
depends_on:
litestream-restore:
condition: service_completed_successfully
# replicate database
litestream-replicate:
image: litestream/litestream:sha-10e25d7c9eb2524254ad533d9bf55a50ec5ac4d7
command: replicate
volumes:
- ./tmp/sqlite:/data
- ./litestream.yml:/etc/litestream.yml:ro
depends_on:
app:
condition: service_healthy
minio には証明書を設定するようにしておきます。こうすることで HTTPS で受け付けるようになります。litestream では https でしか接続できないようになっているための対応です。minio とやり取りするコンテナで証明書のエラーがでます。 minio-client のコンテナの挙動にも影響するため、 --insecure
の option を設定しています。
litestream.yml には skip-verify
を設定しておきます。
dbs:
- path: /data/db.sqlite
replicas:
- type: s3
bucket: mybucket
endpoint: minio:9000
force-path-style: true
skip-verify: true
sync-interval: 1s
access-key-id: user
secret-access-key: password
services に定義してある順にコンテナが動くようになっています。 ざっくり動作を説明すると、
- minio (S3相当) を起動
- minio-client で bucket がなければ作成
- litestream で minio にデータがあれば restore を行う
- sqlite に操作を行う application を起動する
- litestream で minio に replication を行う
のようになります。起動時に細かな設定をする必要ありません。
# make up
docker compose up --build
初回の起動を行うと、minio/mybucket には restore するものがないため local でデータベース及びテーブルの作成を行います。
litesteam-sample-minio-client-1 | Bucket created successfully `myminio/mybucket`.
litesteam-sample-app-1 | driver.Tx(3da7f36c-8b51-4eaf-92be-788b4f3d3874): started
litesteam-sample-app-1 | Tx(3da7f36c-8b51-4eaf-92be-788b4f3d3874).Query: query=PRAGMA foreign_keys args=[]
litesteam-sample-app-1 | Tx(3da7f36c-8b51-4eaf-92be-788b4f3d3874).Query: query=SELECT COUNT(*) FROM `sqlite_master` WHERE `type` = ? AND `name` = ? args=[table users]
litesteam-sample-app-1 | Tx(3da7f36c-8b51-4eaf-92be-788b4f3d3874).Exec: query=CREATE TABLE `users`(`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, `name` varchar(255) NULL, `age` integer NULL) args=[]
litesteam-sample-app-1 | Tx(3da7f36c-8b51-4eaf-92be-788b4f3d3874): committed
litesteam-sample-app-1 | created tables.
シェルをもう一つ用意して確認とユーザーを追加してみます。
curl http://localhost:3000/select
[]
curl http://localhost:3000/insert
{"id":1,"name":"at1653305812","age":11}
curl http://localhost:3000/insert
{"id":2,"name":"at1653305815","age":47}
curl http://localhost:3000/select
[{"id":1,"name":"at1653305812","age":11},{"id":2,"name":"at1653305815","age":47}]
docker compose の output では litestream が replication を行っていることが確認できます。
litesteam-sample-litestream-replicate-1 | litestream 10e25d7c9eb2524254ad533d9bf55a50ec5ac4d7
litesteam-sample-litestream-replicate-1 | initialized db: /data/db.sqlite
litesteam-sample-litestream-replicate-1 | replicating to: name="s3" type="s3" bucket="mybucket" path="" region="" endpoint="minio:9000" sync-interval=1s
litesteam-sample-litestream-replicate-1 | litestream initialization complete
litesteam-sample-litestream-replicate-1 | /data/db.sqlite: init: no wal files available, clearing generation
litesteam-sample-litestream-replicate-1 | /data/db.sqlite: init: no wal files available, clearing generation
litesteam-sample-litestream-replicate-1 | /data/db.sqlite: sync: new generation "a5f4ded6f6104872", no generation exists
litesteam-sample-litestream-replicate-1 | /data/db.sqlite(s3): snapshot written a5f4ded6f6104872/0000000000000000
litesteam-sample-litestream-replicate-1 | /data/db.sqlite(s3): wal segment written: a5f4ded6f6104872/0000000000000000:0000000000000000 sz=16512
次に restore を検証したいので local のデータを消します(rm -rf tmp/sqlite
)。そして、再度 docker compose up
してみます。
すると、 restore を行うコンテナでログが出力されていることがわかります。(litestream-restoreのコンテナでもローカルのデータを削除しますが敢えて)
litesteam-sample-litestream-restore-1 | restoring snapshot 322c6769aca882c0/0000000000000000 to /data/db.sqlite.tmp
litesteam-sample-litestream-restore-1 | applied wal 322c6769aca882c0/0000000000000000 elapsed=63.853833ms
litesteam-sample-litestream-restore-1 | renaming database from temporary location
litesteam-sample-litestream-restore-1 exited with code 0
restore されデータが存在しているはずなので、確認してみます。
curl http://localhost:3000/select
[{"id":1,"name":"at1653305812","age":11},{"id":2,"name":"at1653305815","age":47}]
確かに restore されていることが確認できました。 サクッとできる感じがなんかよいですね!
今回、試すにあたってなんかうまくいかんな〜、みたいな感じで無駄に時間をかけていたのですが @mattn さんが最近公開された記事がとても参考になりました。
mattn さんに感謝しつつ、終わりとしたいと思います〜
以上です〜👋
余談
どうやら http で扱えるようになったようです。
https://t.co/DqqBTp60Hz
— Hiroaki Nakamura (@hnakamur2) May 17, 2022
がマージされました。
環境変数 LITESTREAM_ENDPOINT と LITESTREAM_REGION に加えて
LITESTREAM_SCHEME と LITESTREAM_FORCE_PATH_STYLE が使えるようになりました。
これを使えば docker compose などで localhost ではない minio に http でレプリケートできます。