なんじゃくにっき

プログラミングの話題中心。

無料でDB(データベース)使えるサービスあるの? 2024年春

Herokuに引き続き、PlanetScaleの半永久無料枠が終了してしまいました。

個人開発でサービスを公開したいけど維持費を無料にしたいとか、法人でもサービス開発初期の費用を抑えたいときはどうしましょう、という話。

注意

紹介しているサービスの内容は変更されている可能性があります。また、筆者の調査が不十分なこともあります。

この記事によって損害を被っても補償しかねます。必ず自身の目でサービスの契約内容をお読みになって下さい。

あとデータ容量/通信量等の単位はGBとGiBとか厳密に区別せずに全部GBの表記にしています(1つのサービス内でもドキュメントによって混在したりしていて1つ1つ確認が大変だったため)。

各サービス

RDBMS

Neon

Pricing — Neon

  • postgresqlベース
  • ブランチの機能がある
  • 日本からの最寄りリージョンはシンガポール
  • ガチでRDBMSだけのサービスなので、別途アプリケーション部分は探してこないといけない
  • アプリケーションとNeonのレイテンシを考慮するならシンガポールにアプリケーションを置いたほうが良さそう
  • 無料枠あり
  • 容量0.5GB

Vercel Postgres

  • 上記Neonを使ってVercelのサービスとして提供している
  • Neonを素で使う場合と出来ることが微妙に違うので注意
  • ご存知Nextの開発会社のVercelのサービスの1つ
  • NextとかNuxtとかを無料からホスティングしたいならこれがお手軽そう
  • Hobbyプランなら無料〜

Cloudflare D1

Pricing · Cloudflare D1 docs

  • エッジで動くSQLite
  • 無料枠: 500万行/日
  • 有料プランは $5/月〜(Wokerとセットみたい) + 従量課金
  • Cloudflare Workerから呼び出すことになる

Supabase

https://supabase.com/pricing

  • 読みはスーパーベースらしいです
  • 最近正式サービス化された
  • Firebase代替を謳っている
  • Posgresqlベース
  • 基本的にはAPIで操作する
  • トランザクションを使いたい場合はストアドで
  • RDBMSベースとはいえAPIで操作する以上、直接RDBMSと接続する場合と比べて制限がかかる
  • 無料枠あり(500MBのデータベース容量上限、他帯域などの制限あり)

NoSQL

Firestore(Firebase) / Cloud Datastore

  • DatastoreはFirestoreに統合された
  • 無料枠あり
  • 容量1GB
  • 読み込み5万回/日
  • 書き込み2万回/日
  • ネットワーク下り10 GB/月

MongoDB Atlas

Pricing | MongoDB

  • 無料枠なら容量512MB

DWH(Data ware house)

BigQuery

料金  |  BigQuery: クラウド データ ウェアハウス  |  Google Cloud

  • 無料枠あり
  • 容量10GB
  • read 1TB

比較的安価なサービス

※いっぱいあって調べきれてません

さくらのレンタルサーバ

WordPress、EC-CUBE、concrete5等CMSが使えるスタンダードプラン - レンタルサーバーはさくらインターネット

  • 最下位プランのライトではMySQL使えません
  • スタンダードだと500円/月〜(年契約の場合)
  • お試し2週間

Heroku

  • 昔は半永久無料で使えていた
  • Heroku Postgres が$5から
  • アプリケーション部分は別

PlanetScale

Pricing and plans — PlanetScale

  • 昔は半永久無料で使えていた
  • アプリケーション部分込みで東京リージョンなら $47〜

Render

Pricing | Render

  • お試し90日間
  • 以降は$7〜
  • アプリケーション部分は無料から

期間限定無料枠のあるプラットフォーム

AWS

AWS クラウド無料利用枠 | AWS

利用開始から1年は無料枠があります。その範囲内ならRDS含め無料運用可。

GCP

https://cloud.google.com/free/?hl=ja

利用開始から90日間で$300の無料枠があります。

CloudSQLは含まれなさそう(?)

これが終わってもサービス毎の(半)永久無料枠があります。

僕はこう思ったっス

※個人の感想です

  • 半永久*1、かつ可搬性がある状態*2で無料でDBを使えるのは選択肢はかなり限られます。

  • 汎用的な用途で無料で使えるのは知っている限りではNeonのみ。

  • アーキテクチャが特殊なサービスは自分のやりたいこととがハマれば強力だが、道を外れようとするとつらいので設計をよく考えよう。

  • 将来的にビジネスを成長させるなら最初からお金払うか、AWSGCPの期間限定無料枠を使ったほうが良いのでは・・?

*1:期間の終了が現時点では決まって無いの意。将来的に廃止される可能性がある

*2:他のSaaSにコードほぼそのままで移行できるの意

Astroでローカル開発中に別のマシンから動作確認する

Astroでローカル開発中に別のマシンから動作確認する

Astroで静的サイトの開発中にローカルで動かしている時、別のマシンから動作確認したいときがあります。

スマホ実機での表示、動作の確認をしたいときとかね。

そんなときにデフォルトの状態ではローカルipアドレスでアクセスできません。

http://192.168.0.19:4321/sub_dir みたいな感じ。

そんなときはhostオプションを指定します。

astro dev --host 0.0.0.0

こうすると以下のように標準出力に他のローカルネットワーク上のマシンからアクセスするためのアドレスが出力されます。

(※環境によって出力されるIPアドレスは異なります。念の為。)

┃ Local    http://localhost:4321/sub_dir
┃ Network  http://192.168.0.10:4321/sub_dir

注意

公衆無線LANなどにつないでいる際は有効にしないようにしましょう。

悪戯攻撃される恐れがあります。

デフォルトで有効になっていないのはこういうケースがあるからだと思います。

ボタンが押されたら現在のURLをQRコードにして出力する

この前任意の文字列をQRコードで出力するのをGithub Pagesのお試し用に作ったんですが

百徳ツール | QRコード生成

現在のURLをQR出力するだけのスニペットもほしいかもと思い書いてみました。

というかボタン押してモーダルを出すところまではChatGPTに書かせました。

QR出すところだけ人力(つっても3行くらい)。

ライブラリはqrcodejsを使わせてもらってます。

https://github.com/davidshimjs/qrcodejs

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Modal Example</title>
<style>
  /* スタイルを追加して、モーダルが中央に表示されるようにする */
  dialog {
    width: 80%;
    max-width: 600px;
    padding: 20px;
    border: 1px solid #888;
    background-color: #fefefe;
  }

  /* ボタンを画面の右下に配置するスタイル */
  #myBtn {
    position: fixed;
    bottom: 20px;
    right: 20px;
    padding: 10px 20px;
    font-size: 16px;
    background-color: #007bff;
    color: #fff;
    border: none;
    border-radius: 5px;
    cursor: pointer;
  }
</style>
</head>
<body>

<!-- モーダルを開くボタン -->
<button id="myBtn">Open Modal</button>

<!-- モーダル本体 -->
<dialog id="myModal">
  <button id="closeBtn">&times;</button>
  <div id="qr"></div>
</dialog>

<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
<script>
// ボタンを取得
var btn = document.getElementById("myBtn");

// モーダルを取得
var modal = document.getElementById("myModal");

// 閉じるボタンを取得
var closeBtn = document.getElementById("closeBtn");

// ボタンをクリックした時にモーダルを表示する
btn.onclick = function() {
  modal.showModal();
}

// 閉じるボタンをクリックした時にモーダルを非表示にする
closeBtn.onclick = function() {
  modal.close();
}

new QRCode(document.getElementById("qr"), window.location.href);
</script>
</body>
</html>

既存のHTMLにモーダル出すscriptタグ埋め込むならこんな感じ。

コードは適当です。QRコードクリックで閉じるようになっています。

style当てるなり閉じるボタン作るなりはお好みでどうぞ。

<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
<script>
var modal = document.createElement('dialog');
var qr_area = document.createElement('div');
qr_area.id="qr";
modal.appendChild(qr_area)
document.body.appendChild(modal);
new QRCode(document.getElementById("qr"),window.location.href);
qr_area.onclick = function(){modal.close()}
var btn = document.createElement('button');
btn.textContent = 'QRコード表示';
btn.style.position = 'fixed';
btn.style.bottom = '20px';
btn.style.fontSize = '16px';
btn.onclick = function(){modal.showModal()}
document.body.appendChild(btn);
</script>

ランダムな名前を生成

この前作ったGithub Pagesのサンプルプロジェクト、百徳ツールとか言う名前を付けた割に機能が1つしかなくて、 とても寂しいので機能を追加してみました。

何を作ったの?

ランダム名前 生成

ランダムな名前を生成するものを作りました。日本人の人名ね。

名字と名前をそれぞれランダムに取ってきてくっつけてるだけ。

ここで試せます。

百徳ツール | ランダム名前生成

他、技術的なところでは、prettier入れたり、playwright入れたりしてました。

テストライブラリはjestだかvitestだか何を入れようか悩み中。

ただ、個人開発なのでUnit testもE2Eテストもどこまでちゃんと書くかは分かりません(^^;

余談

今回の機能追加で一番大変だったのは名前のデータを作ることろ。

漢字の名字、名前を集めてくるのはまあ出来るんですが、

そこからフリガナ振るのが全部人力。

名字、男性名、女性名それぞれ100件、計300件を人力で処理したっていう・・

追記

4/18 生成したものをダウンロード可能に

Astroを使って静的サイトを作ってGithub Pagesにデプロイするまで

概要

昨日、静的サイトジェネレーター比較なんて記事を書きましたが、そこで挙げたAstroの使い方です。

基本チュートリアルに従って行けば良く、変更しないといけない箇所はあまりありませんが。

インストール

公式ドキュメントに従います。

Astroを自動CLIでインストール | Docs

※事前にnode.jsのインストールが必要です

npm create astro@latest

と打てば作成するディレクトリを聞いてくるのであとはyesを選択しておけば終わるでしょう。簡単。

Github Pageにインストールする設定

AstroサイトをGitHub Pagesにデプロイする | Docs

astro.config.mjsを編集してsiteとbaseを設定します。

import { defineConfig } from 'astro/config'

export default defineConfig({
  site: 'https://astronaut.github.io',
  base: '/my-repo',
})

siteはastroがサイトマップを正しく生成するのに必要、

baseはGithub Pages内でのリンクを正しく生成するのに必要。

また

.github/workflows/deploy.ymlに公式サイトからファイルをコピペします。

ここまででローカルで

npm run dev

とすると http://localhost:4321/my-repo で起動、

githubのmainブランチpushするとGithub Actionsが起動してGithub Pagesにデプロイされるでしょう。

ここまでで最低限動くのであとは自分の使いたいライブラリを入れていく。

tailwind

@astrojs/tailwind | Docs

npx astro add tailwind

で使えるようになります。

React

npx astro add react

で使えるようになります。

src/components以下のディレクトリにjsxないしtsxでReact Componentを作って

astroファイルのコンポーネントスクリプト部分でimportしたらコンポーネントテンプレート部分で使えるようになります。

---
import Layout from '../layouts/Layout.astro';
import Card from '../components/Card.tsx';
---

<Layout title="ホーム">
  <Card />
</Layout>

他のライブラリ

ライブラリを追加したいときはnpm installして使うのはいつものやつですが、

[vite] Named export 'QRCodeSVG' not found. The requested module 'qrcode.react' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'qrcode.react';
const {QRCodeSVG} = pkg;

みたいなエラーが出ることがあります。

これはviteのnoExternal設定を追加すると解決します。

astro.config.mjs

export default defineConfig({
  site: 'https://nanjakkun.github.io',
  base: '/hyattoku',
  integrations: [react(), tailwind()],
  vite: {
    ssr: {
      noExternal: ["qrcode.react"],
    },
  },
});

GitHub Pagesに使う静的サイトジェネレーター(SSG)比較

概要

以前から静的サイトジェネレーター(SSG)は使っていたんですが、最近特にGithub Pagesにデプロイする用のは何が良いかなーって探していました。

で、色々動かしてみたりしましたが、自分のやりたいことに一番合ってたのはAstroということになりました。

要件

自分が求めている要件は以下

  • 基本はHTML吐いてくれる(ほぼ空のHTMLにjsで描画するのではなく)
  • React Componentを使いたくなったら使える
  • configはあまり書きたくない
  • 動的な部分はTypeScriptで書けてhot reloadが欲しい

Jekyll

Github Pages標準です。

Ruby製だし慣れているのでたまに使っています。JavaScript動かさない場合には楽に動かせて良いんですが、改めて調べてみました。

Viteと一緒に使おうと思うと、jekyll-viteというgemを使えるんですが、

GitHub - ElMassimo/jekyll-vite: ⚡️🩸 Use Vite.js in Jekyll as your assets pipeline

とりあえずローカルで立ち上がるまではサクッと行きます。

そこから先のことをやろうとすると、gemがあまりメンテされていなくドキュメントも少ないので結局vite-rubyとjekyll-viteのソースを読みながらconfigを書いていかないといけないのがつらくなってきました。

で、コンテンツを書いているのかconfigを書いているのか分からなくなってきたのでやめました。

Next

例は多く見つかりますがGithub Pages関係ないところでお仕事で使ったことあり、仕事とは違うことしたいので今回はスキップ。

Gatsby

GitHub - gatsbyjs/gatsby: The best React-based framework with performance, scalability and security built in.

前からちょっと使っていたんですが、React 18にアップデートしたらTypeScriptの型エラーが出るようになってしまいました。(動作自体はするけど型エラーが出続ける)

gatsby -> reach-router -> prop-types -> react-is

の依存でreact-isのバージョンとreactのバージョンが違うと型エラーになるらしいけど、reach-routerもprop-typesも開発止まっててなんともならんということで諦めました。

Hugo

The world’s fastest framework for building websites | Hugo

Go製。あまりViteと組み合わせてGithub Pagesにデプロイしている人を見つけられなかったので断念。

Docusaurus

Build optimized websites quickly, focus on your content | Docusaurus

meta製でReact前提だし、デザインのカスタマイズがしづらそうだったのでちょっと敬遠。

Astro

https://astro.build/

ごく最近までノータッチだったんですが、触ってみてええやん!ってなりました。

今回自分が要件として挙げていたものをほぼ満たしています。

あえて言うなら、styleがデフォルトではテンプレートにベタ書きになっているので別ファイルに切り出したりtailwind入れたりしようと思います。

試しに作ったもの

適当にガチャガチャやりました、だけだと面白みがないので一応役に立つものを作ってみました。

リポジトリ

https://github.com/nanjakkun/hyattoku

Github Pages ↓

https://nanjakkun.github.io/hyattoku/

QRコードが作成できます。それだけ。

QRコード生成

リポジトリ名は百徳とか偉そうな名前ついてますがまだ一徳しかありません。

百個機能付く日は来るのか・・

(最初jittokuって名付けようと思ったんですが、pythonのパッケージであるのを思い出してやめました)

GatsbyのプロジェクトビルドからGitHub PagesにGithub Actionsでデプロイするまで

Gatsbyの初期設定

静的サイトジェネレーターのGatsbyを動かします。Github Pagesにデプロイして動かすまで。

続きを読む

日本語ドメインにプログラムからアクセスする方法

プログラムから日本語ドメインのページにアクセスしたい

例としてRuby、HTTPクライアントとしてFaradayを使ってみます。

アクセス先のドメインは"日本語.jp”にします

https://日本語.jp/

まずはそのまま日本語ドメインでGET

素の日本語ドメイン名でGETしてみます。

$ gem install faraday
$ irb

irb(REPL)を立ち上げて

irb(main):001> require 'faraday'
irb(main):002> Faraday.get('https://日本語.jp')

おもむろにGET。

/hogehoge/.anyenv/envs/rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/uri-0.13.0/lib/uri/rfc3986_parser.rb:84:in `split': URI must be ascii only "https://\u65E5\u672C\u8A9E.jp" (URI::InvalidURIError)

エラーになります。

URIにはascii文字以外使えませんと言われます。そらそーや。

Punycode

日本語ドメインのURLのドメイン部分の符号化は、Punycodeを使う必要があります。(Base64ではなく)

読み方はプニコードかピュニコードです。なんか可愛い。

Punycode - Wikipedia

詳しい解説はサボってwikipediaの記事を見てもらうとします。

変換した結果のURLは

https://xn--wgv71a119e.jp/

になります。

Ruby

Ruby日本語ドメインからpunycodeに変換するにはsimpleidnというgemを使います

$ gem install 'simpleidn'
require 'faraday'
require 'simpleidn'

url = SimpleIDN.to_ascii('https://https://日本語.jp')
res = Faraday.get(url)

Python

Pythonだとそのままの名前のpunycodeというライブラリがあります

$ pip install punycode
import punycode 

domain = punycode.convert("日本語.jp")
req = urllib.request.Request("https://" + domain)
req = urllib.request.Request(url)
with urllib.request.urlopen(req) as res:
    body = res.read()
print(body)

Chrome

ちなみにChrome Developer Tool使ってるとNetworkタブから該当のリクエストを選んで"Copy as url"でpunycode化されたURLを取得することができます。

Cloudflare D1が正式サービスイン

Cloudflare上で動くSQLiteのCloudflare D1がベータ版を抜けてGenerally Availableに(正式サービスイン)。

blog.cloudflare.com

私事ではありますが、アルファ版の頃にちょっと触って、また最近ちょくちょくベータ版を触っていたのでとてもタイムリー。

料金とか

料金はD1単体課金ではなくWorkersと併せてということだと思われる?

有料プラン(Workers Paid)

有料プラン(Workers Paid)は基本料金 $5 で、それに加えて

  • 読み込み行数 100万行あたり$0.001。ただし最初の250億行 / 月までは基本料金に含まれる。
  • 書き込み行数 100万行あたり$1.00。ただし最初の5000万行 / 月 までは基本料金に含まれる。
  • 容量     1GBあたり$0.75。ただし最初の 5 GB までは基本料金に含まれる。

無料プラン

無料プラン(Free)だと

  • 読み込み行数 500万行 / 日。
  • 書き込み行数 10万行 / 日。
  • 容量     5GB。

行数は返却した行数ではなくスキャンした行数なのでフルスキャン走ると一気に加算されます。index貼りましょう。

有料プランは月あたりで、無料プランは日あたりと単位が揃ってないのにも注意。

他制限事項

また、他にも制限事項はドキュメントに書かれています。

Limits · Cloudflare D1 docs

データ行数に応じて従量課金があるならでかいBLOB格納すればお得じゃん、と思いきや1行あたり1MB制限がありますね。

Cloudflare D1の使い途を考える

※この記事はD1がベータ版のときに書かれました

Cloudflare 上で動くSQLiteであるCloudflare D1の使い途を考えるコーナー。

制約

そもそもD1ではないSQLiteではローカルのDBに実行するように作られています。

D1では

  • Cloudflare Workers / Cloudflare Pagesから使う
  • apiエンドポイントにクエリを投げる

のどちらかになります。

つまり他の商用RDBMSのようにリモートにTCP通信で直接接続することができないはずです。(httpはTCP上で動いているとかいう突っ込みは却下)

あまり向いてなさそうなもの

上記の直接Cloufflare外からTCP通信できないという制約から、Cloudflare以外の場所から頻繁に通信が発生するサービスを作るのは、パフォーマンス面からは余り向いてないんじゃないかと思います。

またSQLiteは元々シングルスレッドで動作している都合上、書き込みが頻繁なサービスには厳しそうです。

また、現時点でベータ版で”バックエンドが不安定なためローカルにデータのコピーは用意しておいて下さい”と説明がある以上、失うとクリティカルなデータは保持しない方が良いでしょう。

特にお金に直接関わるデータはやめておいたほうが良いでしょう。

じゃあ何に使えばよいのさ?

じゃあ何に使えるのかというところですが、

書き込みが頻繁なサービスには向かないと前節で書きましたが、逆に書き込み(write)があまりなくて、読み込み(read)がほとんどの場合に真価を発揮すると思われます。データベースがCloudflareのエッジにレプリケーションされているので読み込みはスケールします。

思いついた使い途の例としてはCMS(Contents Management System コンテンツ・マネジメント・システム)系かなーといった感じです。

ブログ

例えば個人用ブログ、会社ブログ。書き込みはたまに記事を更新するときとコメント付けるときくらい。

似たような例で会社のWEBサイトなんかにも使えるケースはあるんじゃないかと。

一点物を売るサイト、不動産屋のサイト

データはバッチで一括更新して、サイトでは商品を見せるだけ。

問い合わせ、商品の購入は別サービスに移動して行ってもらうのを想定。

目録閲覧系

蔵書の検索とか。

予約システムとか複雑になってくるとしんどくなってくるかも?

ちょっと変わった使い方?

サービスを公開するをせずにただローカルから使えるクラウドに存在するRDBMSとして使うという使い方も出来るんじゃないかと考えました。

ローカルで動くツールのバックエンドとして使う想定です。

接続はAPIエンドポイントを叩くか、シェルを呼び出してSQLを流し込む(後者でも内部的にはAPI叩いてますが)。

クラウド上にDBが存在することで、バックアップを任せられるし、複数人で使うこともできます。

書き込みがヘビーな用途にはやっぱり向いてない気はします。

余談

wranglerをインストールしたあと、

node_modules/wrangler/wrangler-dist/cli.js

を覗くとCLIからwranglerが何をしているかある程度分かるので詳しく知りたい人にはオススメです。