Litestream 入りの Dockerfile 作る
Litestream を Dockerfile に同梱して node のなんか動かすやつです。ここでは Next.js & Prisma 構成のサーバー動かします。
主な必要なファイル
- Dockerfile
- litestream.yml
- entrypoint.sh
1. Dockerfile
FROM node:18-alpine as builder ADD . /app WORKDIR /app ADD https://github.com/benbjohnson/litestream/releases/download/v0.3.9/litestream-v0.3.9-linux-amd64-static.tar.gz litestream.tar.gz RUN tar -xzf litestream.tar.gz -C ./ RUN npm install RUN npx prisma generate RUN npm run build FROM node:18-alpine COPY --from=builder /app/next.config.js /next.config.js COPY --from=builder /app/public /public COPY --from=builder /app/package.json /package.json COPY --from=builder /app/.next/static /.next/static COPY --from=builder /app/.next/standalone / COPY --from=builder /app/litestream /usr/local/bin/litestream COPY --from=builder /app/litestream.yml /etc/litestream.yml COPY --from=builder /app/entrypoint.sh /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"]
- litestream のバイナリダウンロードして解凍して、COPY で実行できる場所におきます
- restore したかったので entrypoint.sh にいろいろ書きます
- builder や COPY の部分は物によっていろいろ違いがあると思います
- npx prisma generate で node:18-alpine 用の sqlite3 入ります、後述の schema.prisma の設定が必要
2. litestream.yml
dbs: - path: /tmp/db.sqlite # Database to replicate from replicas: - url: s3://mybkt/litestream # S3-based replication endpoint: http://172.17.0.2:9000 sync-interval: 1s
- ここでは minio を使う想定です、endpoint は minio 起動した時に表示されたものを入れました
3. entrypoint.sh
#!/bin/sh set -e if [ -f /tmp/db.sqlite ]; then rm /tmp/db* fi litestream restore /tmp/db.sqlite litestream replicate -exec "node ./server.js"
- /tmp/db.sqlite にある想定、あったら一旦削除して restore します
- exec で replicate しつつスクリプトを実行できるようです
- /bin/sh と/bin/bash 間違えてハマりました
という感じです。まだ何も作っていない状態だったら以下の感じで諸々入れていけばいいかなと思います。
諸々の入れ方
Next.js
$ npx create-next-app next-prisma-litestream --typescript $ cd next-prisma-litestream
next.config.js 作成
module.exports = { output: 'standalone', }
Prisma
$ npm install --save-dev prisma
$ npx prisma init
.env を修正して sqlite の db を指定 (/tmp/db.sqlite にした)
DATABASE_URL="file:/tmp/db.sqlite"
generator client { provider = "prisma-client-js" binaryTargets = ["native", "linux-musl-openssl-3.0.x"] } datasource db { provider = "sqlite" url = env("DATABASE_URL") } // 動作確認のための適当なテーブル model test { id Int @id @default(autoincrement()) value String }
node:alpine-18
を使う場合 binaryTargets にlinux-musl-openssl-3.0.x
を入れろとエラーで言われたので入れました
マイグレーション実行
$ npx prisma migrate dev
適当なエンドポイント作る
pages/api/hello.ts
import type { NextApiRequest, NextApiResponse } from "next"; import { PrismaClient } from "@prisma/client"; const prisma = new PrismaClient(); type Data = { id: number; value: string; }; const Hello = (req: NextApiRequest, res: NextApiResponse<Data[]>) => { prisma.test .create({ data: { value: new Date().toISOString() }, }) .then(() => prisma.test.findMany()) .then((v) => res.status(200).json(v)); }; export default Hello;
動作確認
minio 起動して Web 画面からバケット作っておきます (mybkt にしました)
$ docker run --rm -p 9000:9000 -p 9001:9001 -v /tmp/minio:/data minio/minio:latest server /data --console-address ":9001"
Dockerfile をビルドして実行します
$ docker build -t ushumpei/next-prisma-litestream:latest . $ docker run --tty --interactive --rm -p3000:3000 --env LITESTREAM_ACCESS_KEY_ID=minioadmin --env LITESTREAM_SECRET_ACCESS_KEY=minioadmin ushumpei/next-prisma-litestream:latest
$ open http://localhost:3000/api/hello
データ表示されてる感じです、再起動しても残る
感想
- litestream は複数の writer 対応していないことを結構調べてから知った
- Lambda & container では無理そう
- ECS on EC2 なら大丈夫そうだけどインスタンス料金はかかる、同時起動制御とかも
- Fargate?
- Cloud Run はどんな感じなんだろう?
- Dockerfile のマルチビルド初めて書いた
- docker のネットワーク全然わからない、雰囲気で書いている
- node:slim-18 とかで書きたかったけどちょっとやってダメだったのでやめました
- litefs は consul server (?) を常時起動する必要がある?