10
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

T3 Stack で作成したアプリを Fly.io にデプロイしてみた

Last updated at Posted at 2022-09-30

はじめに

T3 Stackとは?

simplicity(シンプルさ), modularity(モジュール性), and full-stack typesafety(フルスタックの型安全) に重点をおいて、以下の技術要素で構成されています。

  • Next.js
  • tRPC
  • Tailwind CSS
  • Typescript
  • Prisma
  • NextAuth.js

tRPCは最近目にするようになってきましたが、その他はポピュラーな構成だと思います。
npx create-t3-app@latest を実行して、必要なモジュールを選択するとプロジェクトの雛形が作成されます。

Fly.ioとは?

いわゆる PaaS です。同様のサービスでは Heroku が有名ですね。
無料でアプリをデプロイできて、必要であれば追加のリソースを従量課金で購入できます。
永続ボリュームストレージが使用できるため、 sqlite を配置してデータベースを利用したアプリ開発もできます。

T3 Stackのアプリを作成する

create-t3-app コマンドを実行し、質問に回答します。

回答例
$ npx create-t3-app@latest
 
# プロジェクト名を決めます
? What will your project be called?
t3-app-example
 
# TypeScriptしか勝たん
? Will you be using JavaScript or TypeScript?
o JavaScript
* TypeScript
 
# 今回は認証を実装しないのでnextAuthを外しました
? Which packages would you like to enable?
o nextAuth
* prisma
* tailwind
* trpc
 
# git repositoryは自分で用意するのでNoを選択
? Initialize a new git repository?
No
 
# Yesでnpm installも実行
? Would you like us to run npm install?
Yes
 
# install成功ログ
Using: npm
 
✔ t3-app-example scaffolded successfully!
 
Installing packages...
✔ Successfully installed prisma
✔ Successfully installed tailwind
✔ Successfully installed trpc
✔ Successfully installed envVariables
 
Next steps:
  cd t3-app-example
  npx prisma db push
  npm run dev

次に、上記の Next steps に表示されたコマンドを実行します。

$ cd t3-app-example
$ npx prisma db push
$ npm run dev

http://localhost:3000/ にアクセスすると画面が表示されました。
t3-01.png

あとは生成されたコードを修正して、お好きなアプリを作ってみてください!:muscle_tone2:

開発Tips

Prismaで新しいテーブルを作成する

schema.prisma に model を追加して、 npx prisma db push を実行すると新しいテーブルがDBに作成されます。

prisma/schema.prismaに追記
model Counter {
    id String @id
    count Int
}
$ npx prisma db push
Environment variables loaded from .env
Prisma schema loaded from prisma\schema.prisma
Datasource "db": SQLite database "db.sqlite" at "file:./db.sqlite"
 
Your database is now in sync with your Prisma schema. Done in 42ms
 
✔ Generated Prisma Client (4.3.1 | library) to .\node_modules\@prisma\client in 111ms

tRPCに新しいクエリを作成する

まずはサーバーサイドから実装します。src/server/router 配下に新しいルーティングを追加します。
今回は Prisma を使用して、アクセスカウンターを実装してみました。

src/server/router/example.tsに追記
  .query("countup", {
    async resolve({ ctx }) {
      const pv = await ctx.prisma.counter.upsert({
        where: { id: 'pv' },
        create: { id: 'pv', count: 1 },
        update: { count: {increment: 1}},
      });
      return pv.count;
    },
  })

次に、クライアントサイドを実装します。作成したクエリを呼び出す処理を追加しました。

src/page/index.tsxに追記
 const pv = trpc.useQuery(["example.countup"]);
 console.log(pv.data);

これでページリロードする度に、pv.data がカウントアップされるようになりました。

Fly.ioにデプロイする

CLI tool(flyctl)のインストール

ローカル環境に合わせてインストールコマンドを実行します。公式サイトをご確認ください。

Windowsの場合
> iwr https://fly.io/install.ps1 -useb | iex

アカウントにログイン

ログインコマンドを実行するとWebブラウザにログインページが表示されます。
Sign Inに成功すると、以降そのアカウントに対して操作を実行します。

$ fly auth login

Githubアカウントがある方は連携するとすぐにログインできます。
無料枠内で使用する場合には、クレジットカードの登録などは必要ないようです。
t3-02.png

デプロイの初期設定

fly launch を実行して質問に回答します。
回答が終わると Dockerfile と fly.toml(サーバー構成定義)ファイルが出力されます。

回答例
$ fly launch
Creating app in t3-app-example
Scanning source code
 
# 自動でNextJSアプリとして検出されました
Detected a NextJS app
 
# デプロイするアプリ名を入力します
? App Name (leave blank to use an auto-generated name):
t3-app-example
 
# リージョンは近い方が良いので東京を選択
? Select region:
nrt (Tokyo, Japan)

# すぐにデプロイするか問われますが、 Dockerfileを編集したいのでNoを選択
? Would you like to deploy now?
No
 
Your app is ready. Deploy with `flyctl deploy`

作成されたDockerfileを修正します。

  • 個人的にnpmを使いたいので、yarnコマンドはコメントアウトして、npmコマンドのコメントアウトを解除
  • 環境変数の PORT を fly.toml の internal_port と同じポート番号(8080)に修正
Dockerfileを修正
#RUN yarn install --frozen-lockfile
RUN npm ci
 
#RUN yarn build
RUN npm run build
 
#ENV PORT 3000
ENV PORT 8080
 
#CMD ["yarn", "start"]
CMD ["npm", "run", "start"]

デプロイ

fly deploy コマンドを実行すると、先ほど作成した fly.toml の内容に従ってデプロイされます。

# remoteのbuilderが調子が悪かったので、localでビルドするオプションを追加
$ fly deploy --local-only

管理画面にホスト名が表示されているので、こちらをクリックしてデプロイされたアプリを確認します。
t3-03.png
t3-04.png

トラブルシューティング

Error failed to fetch an image or build from source: error connecting to docker: failed building options: failed probing "personal": context deadline exceeded

fly deploy 実行時にエラーになったので下記ページを参考に fly wireguard websockets enable を実行しました。

Error failed to fetch an image or build from source: error connecting to docker: remote builder app unavailable

何度かデプロイしているとリモートの builder が動かなくなりましたが、管理画面から builder を一度削除することで解決しました。また、--local-only オプションでローカルビルドできたので、途中からはこちらを使用しました。
t3-05.png

Failed due to unhealthy allocations - no stable job version to auto revert to and deploying as v1

何度デプロイしてもヘルスチェックでエラーになっていましたが、しばらく時間をおくとヘルスチェックが通るようになりました。原因は不明です…:disappointed_relieved:

DBのデータを永続ボリュームに保存する

マニュアルを参考に、永続ボリュームを storage という名前でアプリと同じ東京リージョンに1GBで作成しました。

$ fly volumes create storage --region nrt --size 1
        ID: vol_xxxxxxxxxxx
      Name: storage
       App: t3-app-example
    Region: nrt
      Zone: d8a3
   Size GB: 1
 Encrypted: true
Created at: 22 Sep 22 07:30 UTC

続けて fly.toml に永続ボリュームのマウント設定と、 sqlite の保存場所を追記します。

fly.tomlに追記
[mounts]
  source="storage"
  destination="/storage"
 
[env]
  DATABASE_URL="file:/storage/db.sqlite"

アプリ起動時にマイグレーションが走るようにします。

# マイグレーションファイルを作成
$ npx prisma migrate dev
package.jsonに追記
    "prestart": "prisma migrate deploy",

再デプロイし、アプリを再起動してもデータが永続化されていることを確認しました。

# 再デプロイ
$ fly deploy --local-only
 
# 再起動
$ fly restart t3-app-example

おわりに

  • 最初デプロイが上手くいかずに困りましたが、最終的にはデプロイできるようになったので良かったです。
  • 永続ボリュームに直接アクセスする方法が見つけられなかったので、 sqlite のダウンロードは自分で実装する必要があるかもしれません。
  • Prisma, tRPCは初めて触りましたが、使いやすそうでした。
  • アクセスが少ないサイトであれば無料で始められそうなので、今後活用していきたいです。
  • 今回作成したコードのサンプルです。https://github.com/proyuki02/t3-flyio-sqlite-example
10
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?