2
0

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.

DockerコンテナからPlanetScaleに接続する方法とSSLエラーの対処法

Last updated at Posted at 2023-03-20

はじめに

サーバレスだから導入も簡単なんだろうな🤗
と思っていたら盛大にハマってしまったので備忘録を兼ねて投稿します。

DockerコンテナからPlanetScaleに接続しようとすると下記エラーに遭遇したのでその対処法です。
また、記事の後半では動作確認のためNuxt3のCRUD機能も実装しちゃいます。

server does not allow insecure connections, client must use SSL/TLS

以下を前提として解説しています。

  • PlanetScaleにデータベース作成済みであること
  • Nuxt.jsプロジェクト作成済みであること

docker-compose.ymlの設定

PlanetScaleとの通信はSSL接続が必要らしい。
https://planetscale.com/docs/concepts/secure-connections
そのため、volumesでSSL証明書をマウントしておきます。

docker-compose.yml
version: '3'
services:
  web:
    container_name: web
    build: .
    ports:
      - "3000:3000" # Nuxt.js用のポート
      - "5555:5555" # Prisma Studio用のポート
    volumes:
      - "../src:/var/www/html"
      - "/etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/ca-certificates.crt" # ←重要
    tty: true

Dockerfileの設定

FROM node:latest

WORKDIR /var/www/html

RUN apt update && \
    npm install -g npm

EXPOSE 3000
ENV HOST 0.0.0.0

Dockerコンテナを起動

コンテナをビルド、起動します。

docker compose up -d --build

webコンテナに入ります。

docker compose exec web bash

PlanetScaleの設定

登録~DB作成までの流れは下記の記事が参考になると思います。
PlanetScaleというサーバレスDBが凄く勢いのあるサービスらしいのでQuick Startやってみた - Qiita

PlanetScaleのブランチ管理画面にアクセスします。
「New password」ボタンをクリックして接続パスワードを生成します。
image.png

この時、画面に表示される以下の情報を控えておいてください。

  • database
  • username
  • host
  • password

.envファイルの設定

先ほど控えた情報をもとに.envファイルに接続情報を追記します。

.env
DATABASE_URL="mysql://username:password@host/database?sslaccept=strict"

Prismaの設定

Prismaについての解説は本記事ではしません。
参考URLをご覧ください。
Prismaの導入とメリットを考える - Qiita

既存のNuxtプロジェクトのディレクトリに移動します。

cd hoge-project

Prismaをインストールします。

yarn add -D prisma

Prismaを初期化します。

npx prisma init

プロジェクトディレクトリに「prisma/schema.prisma」というファイルが生成されます。
schema.prismaファイルを開いてモデルを定義します。

schema.prisma
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

model User {
  id Int @id @default(autoincrement())
  uid String @unique @db.VarChar(255)
  display_name String @db.VarChar(255)
  created_at DateTime @default(now()) @db.Timestamp(0)
  updated_at DateTime @default(now()) @updatedAt @db.Timestamp(0)
}

モデルの定義情報をPlanetScaleに反映させます。

npx prisma db push

Prisma Clientを生成します。
以下は、モデル定義を変更するたびに実行してください。

npx prisma generate

作成されたDBを確認する

Prisma Studioを起動してDBを確認します。

npx prisma studio

「localhost:5555」をブラウザで開くとアクセスできます。
image.png

CRUDを実装する

ファイル・ディレクトリ構造

CRUD機能を実装するにあたり、以下3つのファイルを作成します。

  • composables/useUser.ts
  • pages/test-prisma.vue
  • server/api/user.ts

表示する側

<template>タグ内にはシンプルにボタンのみを配置しています。
CSSフレームワークにVuetifyを使用しています。

各ボタンの@clickに対応する処理を<script>タグ内に記載しています。
uuidの生成に@faker-js/fakerを使用しています。

onClickUpdateとonClickDeleteの「targetId」の値は必要に応じて修正してください。

pages/test-prisma.vue
<template>
  <div>
    <v-btn @click="onClickCreate">create</v-btn>
    <v-btn @click="onClickRead">read</v-btn>
    <v-btn @click="onClickUpdate">update</v-btn>
    <v-btn @click="onClickDelete">delete</v-btn>
  </div>
</template>

<script setup>
  import {faker} from '@faker-js/faker'

  const { createUser, readUser, updateUser, deleteUser } = useUser()

  const onClickCreate = async () => {
    await createUser({
      uid: faker.datatype.uuid().substring(0, 16),
      display_name: 'Test User'
    })
  }

  const onClickRead  = async () => {
    const data = await readUser()
    console.log(data)
  }

  const onClickUpdate = async () => {
    await updateUser({
      targetId: 1,
      data: {
        uid: faker.datatype.uuid().substring(0, 16),
        display_name: 'テスト ユーザー'
      }
    })
  }

  const onClickDelete = async () => {
    await deleteUser({
      targetId: 1
    })
  }
</script>

実行するコード

再利用可能な関数としてVueコンポーザブルという機能を使います。
動作確認のため、かなりシンプルな実装になっています。

composables/useUser.ts
const useUser = () => {
  /** CREATE */
  const createUser = async (values) => {
    const data = await $fetch('/api/user', {
      method: 'post',
      body: values,
    })
    await refreshNuxtData()
    return data
  }

  /** READ */
  const readUser = async () => {
    const data = await $fetch('/api/user')
    await refreshNuxtData()
    return data
  }

  /** UPDATE */
  const updateUser = async (values) => {
    const data = await $fetch('/api/user', {
      method: 'put',
      body: values,
    })
    await refreshNuxtData()
    return data
  }

  /** DELETE */
  const deleteUser = async (values) => {
    const data = await $fetch('/api/user', {
      method: 'delete',
      body: values,
    })
    await refreshNuxtData()
    return data
  }

  return {
    createUser, readUser, updateUser, deleteUser
  }
}
export default useUser

API

データベースとデータをやり取りするためのAPIを作成します。

server/api/user.ts
import { PrismaClient, Prisma } from '@prisma/client'

export default defineEventHandler(async (e) => {
  const prisma = new PrismaClient()
  const method = e.req.method

  if (method === 'POST') {
    const body = await readBody(e)
    const user = await prisma.user.create({
      data: body
    })
    return user
  }

  if (method === 'GET') {
    const user = await prisma.user.findMany()
    return user
  }

  if (method === 'PUT') {
    const body = await readBody(e)
    const user = await prisma.user.update({
      where: { id: body.targetId },
      data: body.data
    })
    return user
  }

  if (method === 'DELETE') {
    const body = await readBody(e)
    const user = await prisma.user.delete({
      where: { id: body.targetId }
    })
    return user
  }
})

ビルド実行

お疲れさまでした🍺
ビルドを実行します。

yarn dev

「localhost:3000/test-prisma」へアクセスしてください。
下図のような、ボタンだけの画面が表示されているはずです。
image.png

動作確認

Prisma Studio (localhost:5555)へアクセスして各ボタンが機能しているか確認してみましょう。

Create

image.png

Read

image.png

Update

image.png

Delete

image.png

参考サイト

Nuxt3、Firebase、Prismaを利用し、SQL文を書かずに簡単なToDoアプリを作ってみる

2
0
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?