この記事の読者
未来の私です
bkiban.com
ビジネスの基盤、bkiban
というものをつくっていこうと思っています。
db.bkiban
まずデータベースをつくっていこうと思っています。
dbms をつくるわけではなくて、スキーマ定義 (テーブル定義) が簡単にできて、データ投入、更新ができて、csv に出力できるような、そんな感じのものを目指しています。
github
何はなくとも github です。db.bkiban リポジトリをつくりましたので clone してみました
Personal access tokens (2025/4/1)
- GitHubにログイン
- 右上の自分のアカウントアイコンをクリック
- Setttings
- Developper settings
- Personal access tokens > Tokens (classic)
- Generate new token > Generate new token (classic)
- Note: repo_20250401
- Expiration: 90 days
- Select scopes: repo > Generate token
% git clone https://github.com/unrcom/db.bkiban.git
Cloning into 'db.bkiban'...
Username for 'https://github.com': xxxxxx <- Username
Password for 'https://xxxxxx@github.com': <- Personal access token
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
Receiving objects: 100% (3/3), done.
% ls
apache-tomcat-9.0.98 db.bkiban sirokuro-dev7 termlog openjdk proc supa-edgy unrwebpagemui
% cd db.bkiban
% ls
README.md
% cat README.md
# db.bkiban%
%
このページのコードで github の README.md を更新しておきます
% git branch
* main
% git status
On branch main
Your branch is up to date with 'origin/main'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
% git add README.md
% git status
On branch main
Your branch is up to date with 'origin/main'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md
% git commit -m "1st commit"
[main 7220d44] 1st commit
1 file changed, 51 insertions(+), 1 deletion(-)
% git status
On branch main
Your branch is ahead of 'origin/main' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
% git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 1.06 KiB | 1.06 MiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To https://github.com/unrcom/db.bkiban.git
bb36280..7220d44 main -> main
%
github.com 側も更新されて、いい感じになりました
今日はここまで。また明日がんばります
アーキテクチャ
さて github のおうちができたところで Day1 は終了しました。Day2 ではゴリゴリ開発環境をつくっていこうと思っていたのですが、過去メールを整理していたら気になる記事のリンクがありました。
AWS におけるマルチテナント SaaS の実装パターン ~ サーバーレス編
なんというタイムリーな記事なんでしょう。さっそく内容を確認してみました。
理解できたこと (記事からの引用)
- SaaS とはビジネスモデルです。運用の効率性を高め、俊敏性を獲得し、ビジネスのスケールを図るための手段として、SaaS というデリバリーモデルがここ数年で急速にその地位を確立してきました
- 技術的な観点から SaaS を特徴づける要素の最たるものが、いわゆる「コントロールプレーン」と呼ばれる存在です。SaaS では、新しく「テナント」という概念が登場します。複数のテナントが同じシステムを利用するため、それらの管理・運用を効率的に行うメカニズムが必要になります。このコントロールプレーンに含まれる機能は、
- オンボーディング
- テナント管理
- アイデンティティ管理
- メータリング
- 請求
- 階層化 (契約するプランなどに応じてテナントを複数の階層 (tier) に分け、異なる価値や体験を提供する SaaS の構築モデルのこと)
- Amazon ECS SaaS リファレンスアーキテクチャ には3つの構成要素がある
- Web アプリケーション
- コントロールプレーン (SBT: SaaS Contool Plane)
- アプリケーションプレーン
この図は単なるポンチ絵にあらずでして git clone https://github.com/aws-samples/saas-reference-architecture-ecs.git
して、特定のシェルスクリプトを実行すると、実際に動作する環境が自分の aws アカウントにつくれてしまいます (SaaS Builder Toolkit ワークショップ に入門するのが近道思われます)
理解できないこと
- このアイコンはなに?
aws のドキュメントは素晴らしいのですが壮大すぎて、こちらの手が止まってしまいます。いつもの試行錯誤に戻って開発環境を用意したいと思います
Web アプリケーション (2025/4/2)
いつもの Node.js + React + Vercel で進めてみようと思います。しかしながら以前開発環境を構築したのは3年以上前だったと思います。React公式 によると現在では create-react-app は使わないとのこと。Googleで「React 開発環境」で検索すると、さまざまな解説ページや記事がヒットしますが、その多くが create-react-app を使っていますので注意が必要です
現在の状態確認
% git --version
git version 2.39.5 (Apple Git-154)
% python3 -V
Python 3.9.6
% clang --version
Apple clang version 16.0.0 (clang-1600.0.26.6)
Target: arm64-apple-darwin24.0.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
% make --version
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
This program built for i386-apple-darwin11.3.0
% brew -v
Homebrew 4.4.14
% docker version
Client:
Version: 28.0.1
API version: 1.48
Go version: go1.23.6
Git commit: 068a01e
Built: Wed Feb 26 10:38:16 2025
OS/Arch: darwin/arm64
Context: desktop-linux
Server: Docker Desktop 4.39.0 (184744)
Engine:
Version: 28.0.1
API version: 1.48 (minimum version 1.24)
Go version: go1.23.6
Git commit: bbd0a17
Built: Wed Feb 26 10:40:57 2025
OS/Arch: linux/arm64
Experimental: false
containerd:
Version: 1.7.25
GitCommit: bcc810d6b9066471b0b6fa75f557a15a1cbf31bb
runc:
Version: 1.2.4
GitCommit: v1.2.4-0-g6c52b3f
docker-init:
Version: 0.19.0
GitCommit: de40ad0
%
docker network
% docker network ls
NETWORK ID NAME DRIVER SCOPE
c58f288835dd bknet bridge local
6456db5f094c bridge bridge local
17961720e0a5 dumynet bridge local
777b5a0c38b0 host host local
c92a78ea45f6 java_default bridge local
4671f838fd33 none null local
4fa724a5e3f3 sknet bridge local
a88795c525db supabase_network_supa-edgy bridge local
%
db.bkiban.com のネットワークなので bknet を使っていきます
docker-compose.yml
% pwd
/Users/m/Dev/db.bkiban/webapp
% ls
docker-compose.yml
% cat docker-compose.yml
version: '3'
services:
sk:
image: node:latest
container_name: 'dbuser'
hostname: 'dbuser'
ports:
- '3000:3000'
stdin_open: true
tty: true
working_dir: '/var/www/html'
volumes:
- ./src:/var/www/html
networks:
- bknet
networks:
bknet:
external: true
%
コンテナ起動
長らく docker-compose up で起動していましたが、docker compose の現バージョンでは docker composd up です
% docker compose up
WARN[0000] /Users/m/Dev/db.bkiban/webapp/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion
[+] Running 9/9
✔ sk Pulled 30.2s
✔ 545aa82ec479 Pull complete 8.2s
✔ 4378a6c11dea Pull complete 8.6s
✔ 140d15be2fea Pull complete 10.5s
✔ 1d9d474cce08 Pull complete 23.2s
✔ ca40eb2cc73f Pull complete 23.2s
✔ 151918725530 Pull complete 25.0s
✔ 88780de10938 Pull complete 25.0s
✔ a5366786ea25 Pull complete 25.0s
[+] Running 1/1
✔ Container dbuser Created 0.8s
Attaching to dbuser
dbuser | Welcome to Node.js v23.11.0.
dbuser | Type ".help" for more information.
v View in Docker Desktop o View Config w Enable Watch
コンテナ状態確認
コンテナが起動したようなので状態確認します
% docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ce545654df58 node:latest "docker-entrypoint.s…" 27 seconds ago Up 26 seconds 0.0.0.0:3000->3000/tcp dbuser
%
React インストール
コンテナに接続して Next.js (App Router) をインストールしていきます
% docker container exec -it dbuser /bin/bash
root@dbuser:/var/www/html# pwd
/var/www/html
root@dbuser:/var/www/html# ls
root@dbuser:/var/www/html# npx create-next-app@latest
Need to install the following packages:
create-next-app@15.2.4
Ok to proceed? (y) y
✔ What is your project named? … my-app
✔ Would you like to use TypeScript? … No / Yes
✔ Would you like to use ESLint? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like your code inside a `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to use Turbopack for `next dev`? … No / Yes
✔ Would you like to customize the import alias (`@/*` by default)? … No / Yes
Creating a new Next.js app in /var/www/html/my-app.
Using npm.
Initializing project with template: app-tw
Installing dependencies:
- react
- react-dom
- next
Installing devDependencies:
- typescript
- @types/node
- @types/react
- @types/react-dom
- @tailwindcss/postcss
- tailwindcss
added 48 packages, and audited 49 packages in 14s
10 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Success! Created my-app at /var/www/html/my-app
npm notice
npm notice New major version of npm available! 10.9.2 -> 11.2.0
npm notice Changelog: https://github.com/npm/cli/releases/tag/v11.2.0
npm notice To update run: npm install -g npm@11.2.0
npm notice
root@dbuser:/var/www/html#
React Router (v7)
root@dbuser:/var/www/html# npx create-react-router@latest
Need to install the following packages:
create-react-router@7.4.1
Ok to proceed? (y) y
npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported
create-react-router v7.4.1
dir Where should we create your new project?
/my-app
◼ Using default template See https://github.com/remix-run/react-router-templates for more
✔ Template copied
git Initialize a new git repository?
No
deps Install dependencies with npm?
Yes
✔ Dependencies installed
done That's it!
Enter your project directory using cd ./../../../my-app
Check out README.md for development and deploy instructions.
Join the community at https://rmx.as/discord
root@dbuser:/var/www/html#
ローカル (開発) サーバの起動
どうやって開発サーバを起動するのでしょうか。公式ページには記載がなく、昔の記憶を頼りに package.json のなかを見ながら起動してみます
root@dbuser:/var/www/html# ls
my-app
root@dbuser:/var/www/html# cd my-app/
root@dbuser:/var/www/html/my-app# ls
README.md app next-env.d.ts next.config.ts node_modules package-lock.json package.json postcss.config.mjs public tsconfig.json
root@dbuser:/var/www/html/my-app# cat package.json
{
"name": "my-app",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"react": "^19.0.0",
"react-dom": "^19.0.0",
"next": "15.2.4"
},
"devDependencies": {
"typescript": "^5",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"@tailwindcss/postcss": "^4",
"tailwindcss": "^4"
}
}
root@dbuser:/var/www/html/my-app# npm run dev
> my-app@0.1.0 dev
> next dev --turbopack
▲ Next.js 15.2.4 (Turbopack)
- Local: http://localhost:3000
- Network: http://172.19.0.2:3000
✓ Starting...
Attention: Next.js now collects completely anonymous telemetry regarding usage.
This information is used to shape Next.js' roadmap and prioritize features.
You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL:
https://nextjs.org/telemetry
✓ Ready in 1145ms
○ Compiling / ...
✓ Compiled / in 2.6s
GET / 200 in 2808ms
✓ Compiled /favicon.ico in 426ms
GET /favicon.ico?favicon.45db1c09.ico 200 in 486ms
ブラウザから localhost:3000 に接続してみます
デプロイ
Vercel にデプロイしてみます
- ここまでのコードを github に push
- Vercel にログイン
- [Add new Project]
- プロジェクト名: db-bkiban > [Build it]
- インポートする Git リポジトリの [import] をクリック
- Framework Preset に Next.js を選択
- Root Directory の [Edit] をクリック > V マークが表示されるフォルダを指定する > デプロイ
花びらというか紙吹雪が舞わなくなりましたね
プラウザから接続してみます
今日はここまでにして、また明日、がんばります
AWS 請求アラート
本題とは関係がないのですが、2025年3月の AWS の請求が思いのほか高額になりまして、サービスごとに確認してみました。結果は CloudWatch の東京リージョンでの利用料が多くなっておりましてメトリクスを確認したところ身に覚えのないメトリクスが大量に登録されていました。DynamoDB に関するものが多く、DynamoDB 自体はほぼ無料で使えたのにメトリクスで課金されるという、あるあるなのでしょうか? 気をつけたいと思います
db.bkiban でも AWS のサービス利用を予定していますので、今のうちに請求アラートを設定しておこうと思います
- AWS コンソールの検索で「Billing and Cost Management」
- 左側のハンバーガーメニューから「請求設定」
こんな感じに設定
- AWS コンソールの検索で「CloudWatch」
- リージョンが「米国東部 (バージニア北部)」であることを確認
- [アラーム] > [すべてのアラーム]
- [アラームの作成]
- [メトリクスの選択]
- [Billing]
- [概算合計請求額]
- 「USD」の左側のチェックを入れて > [メトリクスの選択]
- 「...よりも」にアラームをとばす閾値を入力 > [次へ]
- [新しいトピックの作成]
- トピック名 と メールアドレス を入力して [トピックの作成]
アラートがくるのが楽しみです
認証
では Web アプリケーション に認証機能を実装していこうと思います。認証は AWS Cognito を使ってみようと思っていまして、よくある メールアドレス + パスワード による認証を行います。ここで一つ工夫したいことがありまして、「お試しユーザ」は認証なしで使えるようしたくて、この機能を Firebase の「匿名認証」で実現しようと思っています
AWS Cognito 部分は以下のようにつくっていこうと思っています
CloudFront を間にいれるべき、とは思いますが、とりあえずは必要最低限で構成します
Firebase 側は、Web アプリケーションから Firebase API を直接呼び出します
ちょっと寄り道
Web アプリケーション に認証機能を組み込む際に使用する Web ページ をつくっていたら、だいぶ時間を使ってしまいました
Firebase
Firebase アカウントは持っているのでログインし、プロジェクトを作成しました。以降は Firebase ドキュメントの JavaScript を使用して Firebase 匿名認証を行う に従って実装していきます
今日はここまでにして、また明日、頑張ります