どうもてぃ。
作りました。興味がある人は気軽に触ってみてください。
当該リポジトリ
デプロイ手順
前提として pscale
コマンド、flyctl
コマンドが実行できるようにしておいてください。npm(yarn)が入ってないのは論外で。
PlanetScaleの作成
$ pscale auth login $ pscale database create nestjs-sample --region ap-northeast $ pscale branch create nestjs-sample dev $ pscale branch promote nestjs-sample main $ pscale password create nestjs-sample dev <name> # nameは識別子なのでなんでもおk
pscale password list
でも取得できますが、DATABASE_URL
の形式に書き換えるのだるいのでPlanetScaleのダッシュボードで確認してください。
データベース → connectで表示されます。
passwordがまだ作成できてない場合は New password
を押しましょう。DATABASE_URL
が出来上がったらコピーしておいてください。flyctl
で使用します。
Fly.ioの作成
$ flyctl auth login # databaseはPlanetScaleを使用するのでNo # Dockerfileを上書きしないように注意 # Dockerfileがあるため最後にデプロイするかどうか聞かれますがNoで(DATABASE_URLを設定してないため) # fly.tomlは上書きしてください $ flyctl launch # DATABASE_URLは上でコピーしたやつ # 後ろのパラメータ大事、絶対忘れるな $ flyctl secrets set DATABASE_URL="mysql://~~~~~~~~~~~~~~~~~~~~~~~~~/nestjs-sample?sslaccept=strict?sslcert=/etc/ssl/certs/ca-certificates.crt" $ flyctl deploy
特に問題なければデプロイできているでしょう、きっとね。
苦労したこと
WLS2環境で認証画面が立ち上がらない
最初 pscale
コマンドでPlanetScaleへschema.prismaを反映させようとしていました。
が、まず pscale auth login
ではまった。
chromeが立ち上がらない。ctrl + c
でキャンセルすると認証画面のURLが表示されるが、アクセスしても無効化されている(そりゃそうだ)。
wsl2だとやっぱりpscaleコマンドでchrome立ち上がらないっぽいな。issueあがっておりますがな。https://t.co/lHXDzIuUza
— もてぃ💪Engineer (@nil_motty93) 2023年1月29日
wsl2でpscaleコマンド使う場合はいったんsudoじゃないとうまくいかん。
— もてぃ💪Engineer (@nil_motty93) 2023年1月29日
あと、/root/.config/planetscaleディレクトリを作っておく必要があって、sudo pscale auth loginした後のアクセストークンがここに入る。
根本的にはまだ解決できていませんが、いったんsudoで実行し生成したアクセストークンを実行ユーザーのディレクトリに移動させることでうまくいきました。
wsl2環境ではpscale auth loginはスーパーユーザーで行い、生成されたアクセストークンを実行ユーザーのディレクトリに移動させる…という厄介なムーブが必要になることが判明したので、追記コメントした。https://t.co/lHXDzIuUza
— もてぃ💪Engineer (@nil_motty93) 2023年1月30日
解決したのでこのissueにコメントしときました。OSS活動じゃん。
根本解決は↓を今度ためしてみる予定。
ちなみに、pscale
コマンドだけでなくflyctl
コマンドでもCLI認証する必要があり、同じようにスーパーユーザーで実行し、アクセストークンを移動させるというムーブをしました。
くっそだる。
MacやLinux使ってる人は関係ないのでスルーでおkです。
Fly.ioでPrismaInitializationErrorが発生
Fly.ioにデプロイするタイミングでPlanetScaleにスキーマ構造を反映させているのですが、その際 PrismaInitializationError
が発生しデプロイに失敗していました。
長いですが以下
~/github.com/planetscale.nestjs-graphql-prisma main* % sudo flyctl deploy [sudo] password for motty: Update available 0.0.446 -> v0.0.451. Run "flyctl version update" to upgrade. ==> Verifying app config --> Verified app config ==> Building image Remote builder fly-builder-bitter-wave-2664 ready ==> Creating build context --> Creating build context done ==> Building image with Docker --> docker host: 20.10.12 linux x86_64 Sending build context to Docker daemon 191.9kB [+] Building 57.6s (18/18) FINISHED => [internal] load remote build context 0.0s => copy /context / 0.1s => [internal] load metadata for docker.io/library/debian:bullseye 2.0s => [stage-1 1/8] FROM docker.io/library/debian:bullseye@sha256:534da5794e770279c889daa891f46f5a530b0c5de8bfbc5e40394a0164d9fa87 0.0s => CACHED [builder 2/7] RUN apt-get update; apt install -y curl python-is-python3 pkg-config build-essential 0.0s => CACHED [builder 3/7] RUN curl https://get.volta.sh | bash 0.0s => CACHED [builder 4/7] RUN volta install node@18.8.0 yarn@1.22.19 0.0s => CACHED [builder 5/7] WORKDIR /app 0.0s => [builder 6/7] COPY . . 0.0s => [builder 7/7] RUN yarn install && yarn prisma generate && yarn build 49.7s => CACHED [stage-1 2/8] WORKDIR /app 0.0s => CACHED [stage-1 3/8] COPY --from=builder /root/.volta /root/.volta 0.0s => CACHED [stage-1 4/8] COPY --from=builder /app/node_modules ./node_modules/ 0.0s => [stage-1 5/8] COPY --from=builder /app/dist ./dist 0.1s => [stage-1 6/8] COPY --from=builder /app/.fly ./.fly 0.2s => [stage-1 7/8] COPY --from=builder /app/package.json ./ 0.1s => [stage-1 8/8] COPY --from=builder /app/yarn.lock ./ 0.0s => exporting to image 0.1s => => exporting layers 0.1s => => writing image sha256:393032d20e1b39441cedd0abc72eff5352edb0a377daedd8e0dabf6c293d7aa3 0.0s => => naming to registry.fly.io/nestjs-app:deployment-01GR1MYTD32RT3HDPMPYEGNK86 0.0s --> Building image done ==> Pushing image to fly The push refers to repository [registry.fly.io/nestjs-app] 1e854d6563d3: Pushed 1d6767cc453b: Pushed f7e90164f428: Pushed fbf3a65b1a93: Pushed 5d3c3bdc31ec: Layer already exists 5b1800ba7f88: Layer already exists 1b526d844305: Layer already exists a9099c3159f5: Layer already exists deployment-01GR1MYTD32RT3HDPMPYEGNK86: digest: sha256:0e210bfe9ec945b3e5c9cd95571ca559e3db8eaa140cba21b0fdec2cba066698 size: 1996 --> Pushing image done image: registry.fly.io/nestjs-app:deployment-01GR1MYTD32RT3HDPMPYEGNK86 image size: 847 MB ==> Creating release --> release v3 created --> You can detach the terminal anytime without stopping the deployment ==> Monitoring deployment Logs: https://fly.io/apps/nestjs-app/monitoring 1 desired, 1 placed, 0 healthy, 1 unhealthy [restarts: 2] [health checks: 1 total, 1 critical] Failed Instances Failure #1 Instance ID PROCESS VERSION REGION DESIRED STATUS HEALTH CHECKS RESTARTS CREATED cca60ea1 app 3 nrt run failed 1 total, 1 critical 2 46s ago Recent Events TIMESTAMP TYPE MESSAGE 2023-01-30T15:34:25Z Received Task received by client 2023-01-30T15:34:25Z Task Setup Building Task Directory 2023-01-30T15:34:51Z Started Task started by client 2023-01-30T15:34:57Z Terminated Exit Code: 1 2023-01-30T15:34:57Z Restarting Task restarting in 1.14956903s 2023-01-30T15:35:04Z Started Task started by client 2023-01-30T15:35:10Z Terminated Exit Code: 1 2023-01-30T15:35:10Z Restarting Task restarting in 1.058345s 2023-01-30T15:35:17Z Started Task started by client 2023-01-30T15:35:23Z Terminated Exit Code: 1 2023-01-30T15:35:23Z Not Restarting Exceeded allowed attempts 2 in interval 5m0s and mode is "fail" 2023-01-30T15:35:23Z Alloc Unhealthy Unhealthy because of failed task 2023-01-30T15:35:20Z [info][Nest] 659 - 01/30/2023, 3:35:20 PM LOG [InstanceLoader] ConfigHostModule dependencies initialized +1ms 2023-01-30T15:35:20Z [info][Nest] 659 - 01/30/2023, 3:35:20 PM LOG [InstanceLoader] AppModule dependencies initialized +0ms 2023-01-30T15:35:20Z [info][Nest] 659 - 01/30/2023, 3:35:20 PM LOG [InstanceLoader] PostsModule dependencies initialized +1ms 2023-01-30T15:35:20Z [info][Nest] 659 - 01/30/2023, 3:35:20 PM LOG [InstanceLoader] ConfigModule dependencies initialized +1ms 2023-01-30T15:35:20Z [info][Nest] 659 - 01/30/2023, 3:35:20 PM LOG [InstanceLoader] AuthorsModule dependencies initialized +0ms 2023-01-30T15:35:20Z [info][Nest] 659 - 01/30/2023, 3:35:20 PM LOG [InstanceLoader] GraphQLSchemaBuilderModule dependencies initialized +0ms 2023-01-30T15:35:20Z [info][Nest] 659 - 01/30/2023, 3:35:20 PM LOG [InstanceLoader] GraphQLModule dependencies initialized +1ms 2023-01-30T15:35:21Z [info][Nest] 659 - 01/30/2023, 3:35:21 PM LOG [RoutesResolver] AppController {/}: +199ms 2023-01-30T15:35:21Z [info][Nest] 659 - 01/30/2023, 3:35:21 PM LOG [RouterExplorer] Mapped {/, GET} route +4ms 2023-01-30T15:35:21Z [info]prisma:info Starting a mysql pool with 3 connections. 2023-01-30T15:35:21Z [info][Nest] 659 - 01/30/2023, 3:35:21 PM LOG [PrismaService] info: Starting a mysql pool with 3 connections. 2023-01-30T15:35:21Z [info]/app/node_modules/@prisma/client/runtime/index.js:24780 2023-01-30T15:35:21Z [info] throw new PrismaClientInitializationError(error2.message, this.config.clientVersion, error2.error_code); 2023-01-30T15:35:21Z [info] ^ 2023-01-30T15:35:21Z [info]PrismaClientInitializationError: Error opening a TLS connection: error:16000069:STORE routines:func(0):unregistered scheme:../deps/openssl/openssl/crypto/store/store_register.c:237:scheme=file, error:80000002:system library:func(0):reason(2):../deps/openssl/openssl/providers/implementations/storemgmt/file_store.c:267:calling stat(/etc/ssl/certs), error:16000069:STORE routines:func(0):unregistered scheme:../deps/openssl/openssl/crypto/store/store_register.c:237:scheme=file, error:80000002:system library:func(0):reason(2):../deps/openssl/openssl/providers/implementations/storemgmt/file_store.c:267:calling stat(/etc/ssl/certs), error:16000069:STORE routines:func(0):unregistered scheme:../deps/openssl/openssl/crypto/store/store_register.c:237:scheme=file, error:80000002:system library:func(0):reason(2):../deps/openssl/openssl/providers/implementations/storemgmt/file_store.c:267:calling stat(/etc/ssl/certs), error:16000069:STORE routines:func(0):unregistered scheme:../deps/openssl/openssl/crypto/store/store_register.c:237:scheme=file, error:80000002:system library:func(0):reason(2):../deps/openssl/openssl/providers/implementations/storemgmt/file_store.c:267:calling stat(/etc/ssl/certs), error:0A000086:SSL routines:func(0):certificate verify failed:../deps/openssl/openssl/ssl/statem/statem_clnt.c:1896: (unable to get local issuer certificate) 2023-01-30T15:35:21Z [info] at startFn (/app/node_modules/@prisma/client/runtime/index.js:24780:17) 2023-01-30T15:35:21Z [info] at async Proxy.onModuleInit (/app/dist/src/prisma/prisma.service.js:40:9) 2023-01-30T15:35:21Z [info] at async Promise.all (index 0) 2023-01-30T15:35:21Z [info] at async callModuleInitHook (/app/node_modules/@nestjs/core/hooks/on-module-init.hook.js:43:5) 2023-01-30T15:35:21Z [info] at async NestApplication.callInitHook (/app/node_modules/@nestjs/core/nest-application-context.js:178:13) 2023-01-30T15:35:21Z [info] at async NestApplication.init (/app/node_modules/@nestjs/core/nest-application.js:96:9) 2023-01-30T15:35:21Z [info] at async NestApplication.listen (/app/node_modules/@nestjs/core/nest-application.js:158:33) 2023-01-30T15:35:21Z [info] at async bootstrap (/app/dist/src/main.js:11:5) { 2023-01-30T15:35:21Z [info] clientVersion: '4.9.0', 2023-01-30T15:35:21Z [info] errorCode: 'P1011' 2023-01-30T15:35:21Z [info]} 2023-01-30T15:35:21Z [info]Node.js v18.8.0 2023-01-30T15:35:21Z [info]error Command failed with exit code 1. 2023-01-30T15:35:21Z [info]info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command. 2023-01-30T15:35:21Z [info]Starting clean up. --> v3 failed - Failed due to unhealthy allocations - no stable job version to auto revert to and deploying as v4 --> Troubleshooting guide at https://fly.io/docs/getting-started/troubleshooting/ Error abort
Dockerfileに関しては flyctl launch
した際に生成されるDockerfileで少しばかりカスタマイズしています。
似た問題のIssueを見つけました。
sslcert pathを設定しないといけない…と。しかもそれがPrisma公式に書いてあった。
PlanetScaleにもdebianだったらこれ設定しろよって書いてました。
そしてflyctl launchして生成されるDockerfileのdebian:bullseye
imageには、なんと/etc/ssl
ディレクトリがなかった。証明書が存在しなかったのです…。
これはコンテナを立てて確認済みです。
正しくはbuilder imageではcurlをいれてるので証明書ca-certificates.crt
はあるのですが、実行image には存在してませんでした。
そのため、実行imageの方にCOPYしてあげる必要があった…と(apt installする手もありますが、実行imageが肥大化するので無し)。
FROM debian:bullseye as builder ARG NODE_VERSION=18.8.0 ARG YARN_VERSION=1.22.19 ENV NODE_ENV development ENV VOLTA_HOME /root/.volta ENV PATH /root/.volta/bin:$PATH RUN apt update && \ apt install -y curl python-is-python3 pkg-config build-essential apt-transport-https RUN curl https://get.volta.sh | bash RUN volta install node@${NODE_VERSION} yarn@${YARN_VERSION} WORKDIR /app COPY . . RUN yarn install && \ yarn prisma generate && \ yarn build FROM debian:bullseye ENV NODE_ENV production ENV PATH /root/.volta/bin:$PATH LABEL fly_launch_runtime="nodejs" WORKDIR /app COPY --from=builder /root/.volta /root/.volta COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/dist ./dist COPY --from=builder /app/.fly ./.fly COPY --from=builder /app/package.json ./ COPY --from=builder /app/yarn.lock ./ COPY --from=builder /etc/ssl /etc # これが必要!!!!!! CMD ["sh", ".fly/start.sh"]
あとDATABASE_URLにパラメータを設定したものをsecretsに反映させます。
$ flyctl secrets set DATABASE_URL='mysql://~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/nestjs-sample?sslaccept=strict?sslcert=/etc/ssl/certs/ca-certificates.crt'
これで無事認証も通り flyctl deploy
でPrisma schemaをPlanetScaleへ反映させることができました。
おめでとう。
おわり
私はいつも会社で新規プロジェクトが始まると、新しい技術を取り入れようとし一瞬で作れるリポジトリ作成マンになります。
自分にとっても会社にとっても他のエンジニア様たちにとってもメリットしかないので今後も続けていきてぇっすね。
ぜひぜひ使ってみてね。
これであなたもモダンなインフラを扱えるようになりますよぉ。
次はRenderかRailwayでデプロイする記事書こうかな。