クイックスタート:5分でPocketBaseを起動する
PocketBaseは単一の実行ファイルとして提供されます。ダウンロードして起動するだけで、データベース・REST API・認証・ファイルストレージ・管理ダッシュボードがすべて揃ったバックエンドが手に入ります。DockerもNode.jsもPostgresも不要です。
Linuxで起動する手順は以下のとおりです:
# 最新リリースをダウンロード(現在のバージョンはhttps://pocketbase.io/docsで確認)
wget https://github.com/pocketbase/pocketbase/releases/download/v0.22.0/pocketbase_0.22.0_linux_amd64.zip
# 解凍する
unzip pocketbase_0.22.0_linux_amd64.zip
# 実行権限を付与して起動
chmod +x pocketbase
./pocketbase serve
次のような出力が表示されます:
2024/01/15 10:00:00 サーバーが http://127.0.0.1:8090 で起動しました
- REST API: http://127.0.0.1:8090/api/
- Admin UI: http://127.0.0.1:8090/_/
ブラウザでhttp://127.0.0.1:8090/_/を開きます。プロンプトが表示されたら管理者アカウントを作成すると、ダッシュボードにアクセスできます。
macOSも同じ手順です。darwinビルドをダウンロードしてください。Windowsの場合はWindows用のzipをダウンロードし、コマンドプロンプトからpocketbase.exe serveを実行します。
最初のコレクションを作成する
コレクションはデータベースのテーブルだと考えてください。管理ダッシュボードで新しいコレクションをクリックし、名前をpostsとして以下のフィールドを追加します:
- title — テキスト、必須
- content — エディタ(リッチテキスト)
- published — ブール値
- author — リレーション(
usersコレクションへのリンク)
保存します。PocketBaseは新しいコレクションのREST APIを自動生成します。コードを一切書かずに/api/collections/posts/recordsエンドポイントが使えるようになります。
詳細解説:APIの操作
REST APIは既存の規約に従っています。すべてのコレクションに同じエンドポイントが用意されており、URLパラメータでフィルタリング・ソート・ページネーションが可能です。
レコードの取得
# 全投稿を取得
curl http://127.0.0.1:8090/api/collections/posts/records
# フィルタリングとソート
curl "http://127.0.0.1:8090/api/collections/posts/records?filter=(published=true)&sort=-created&perPage=10"
# IDで特定のレコードを取得
curl http://127.0.0.1:8090/api/collections/posts/records/RECORD_ID
レコードの作成と更新
# 新しい投稿を作成(コレクションルールで認証が必要な場合はトークンが必要)
curl -X POST http://127.0.0.1:8090/api/collections/posts/records \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{"title": "最初の投稿", "content": "Hello World", "published": true}'
# レコードを更新
curl -X PATCH http://127.0.0.1:8090/api/collections/posts/records/RECORD_ID \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{"published": false}'
認証
ユーザー管理は最初から組み込まれています。usersコレクションは最初から存在しており、自分で作成する必要はありません。登録とログインは以下のとおりです:
# 新しいユーザーを登録
curl -X POST http://127.0.0.1:8090/api/collections/users/records \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "password": "password123", "passwordConfirm": "password123"}'
# ログインしてトークンを取得
curl -X POST http://127.0.0.1:8090/api/collections/users/auth-with-password \
-H "Content-Type: application/json" \
-d '{"identity": "[email protected]", "password": "password123"}'
ログインレスポンスにはtokenフィールドが含まれます。以降のリクエストではAuthorization: Bearer TOKENとして渡してください。
JavaScript SDKの使用
フロントエンド開発では、公式のJavaScript SDKを使うとfetchを直接呼び出すよりもすっきりします:
npm install pocketbase
import PocketBase from 'pocketbase';
const pb = new PocketBase('http://127.0.0.1:8090');
// ログイン
const authData = await pb.collection('users').authWithPassword('[email protected]', 'password123');
// 投稿を取得
const posts = await pb.collection('posts').getList(1, 20, {
filter: 'published = true',
sort: '-created',
});
// 投稿を作成
const newPost = await pb.collection('posts').create({
title: 'SDKからこんにちは',
content: 'これは私の投稿です',
published: true,
});
応用:リアルタイムサブスクリプションとファイルアップロード
Subscribeによるリアルタイム更新
リアルタイム更新こそがPocketBaseの真骨頂です。コレクションを購読すると、変更が発生した瞬間にクライアントへ届きます。ポーリングも手動のリフレッシュロジックも不要です:
// 'posts'コレクションの全変更を購読
await pb.collection('posts').subscribe('*', function(e) {
console.log('アクション:', e.action); // 'create'、'update'、または'delete'
console.log('レコード:', e.record);
});
// 特定のレコードを購読
await pb.collection('posts').subscribe('RECORD_ID', function(e) {
console.log('この投稿が変更されました:', e.record);
});
// 完了時に購読を解除(コンポーネントのアンマウント時など)
pb.collection('posts').unsubscribe('*');
PocketBaseはWebSocketではなくSSE(Server-Sent Events)を内部で使用しています。そのため、特別な設定なしで大半のファイアウォールやプロキシを通過できます。
ファイルアップロード
管理ダッシュボードでコレクションにファイルフィールドを追加し、APIからファイルをアップロードします:
const formData = new FormData();
formData.append('title', '添付ファイル付きの投稿');
formData.append('attachment', fileInput.files[0]);
const record = await pb.collection('posts').create(formData);
// ファイルのURLを取得
const fileUrl = pb.files.getUrl(record, record.attachment);
コレクションルールとアクセス制御
各コレクションには読み取り・作成・更新・削除のAPIルールがあります。レコードのクエリと同じPocketBaseのフィルタ構文を使用します:
- 空欄 → 誰でもアクセス可能(公開読み取りに最適)
@request.auth.id != ""→ 認証済みユーザーのみauthor = @request.auth.id→ レコードの投稿者のみ@request.auth.id = @collection.admins.id→ 管理者のみ
一般的なブログ設定では、List/ViewルールはそのままにしてPostsを公開にします。作成には認証が必要です。更新/削除にはauthor = @request.auth.idが必要です。
Goフックによる拡張
カスタムのサーバーサイドロジックが必要な場合は、PocketBaseをGoアプリに組み込んでフックを追加できます:
go mod init myapp
go get github.com/pocketbase/pocketbase
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// 投稿作成後にメールを送信
app.OnRecordAfterCreateRequest("posts").Add(func(e *core.RecordCreateEvent) error {
log.Println("新しい投稿が作成されました:", e.Record.GetString("title"))
// メール送信、Webhookトリガーなど
return nil
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
実践的なヒント
本番環境でのPocketBaseの運用
VPSでは、PocketBaseをsystemdサービスとして管理することで、起動時に自動で開始され、クラッシュ後も自動再起動されます:
# /etc/systemd/system/pocketbase.service
[Unit]
Description=PocketBaseサービス
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/pocketbase
ExecStart=/opt/pocketbase/pocketbase serve --http=0.0.0.0:8090
Restart=always
[Install]
WantedBy=multi-user.target
sudo systemctl enable pocketbase
sudo systemctl start pocketbase
HTTPSを処理するためにNginxをリバースプロキシとして使用します。見落としがちなポイント:プロキシバッファリングを無効にしないと、SSE接続が無音のまま止まります:
location / {
proxy_pass http://127.0.0.1:8090;
proxy_set_header Host $host;
# SSE(リアルタイムサブスクリプション)に重要
proxy_buffering off;
proxy_read_timeout 3600;
}
バックアップ戦略
レコード・ユーザー・設定などすべてのデータはpb_data/data.dbという単一のSQLiteファイルに保存されます。バックアップはファイルを1つコピーするだけです:
# シンプルな日次バックアップ
0 2 * * * cp /opt/pocketbase/pb_data/data.db /backups/pocketbase-$(date +%Y%m%d).db
管理APIを使えば、サーバーを停止せずにバックアップをトリガーすることもできます。
データインポートのワークフロー
既存データをPocketBaseに移行する際、旧システムからのCSVエクスポートをインポート前にJSONに変換する必要があることがよくあります。私がよく使うのはtoolcraft.app/ja/tools/data/csv-to-jsonです。ブラウザ上で完結するためデータが手元を離れません。CSVにユーザー情報や機密レコードが含まれている場合は特に重要です。JSONが手に入れば、簡単なスクリプトでPocketBaseのAPIを通じて一括インサートできます。
PocketBaseを使うべき場面(使わないべき場面)
PocketBaseが適している場面:
- サイドプロジェクトやMVPを作っていて、1時間でバックエンドを動かしたい
- 単一サーバーで十分な場合 — 社内ツール、管理ダッシュボード、小規模モバイルアプリ
- 自前で管理する複雑さなしにモバイルアプリのオフライン同期が必要な場合
- プロトタイプ段階でフルスタックにコミットしたくない場合
適していない場面:
- 複数サーバーへの水平スケーリングが必要なアプリ — SQLiteは分散書き込みに対応していない
- 高書き込み負荷:SQLiteは並行読み取りは得意ですが、競合状態では秒間数百件の書き込みを超えると苦しくなる
- 複雑なSQLクエリ、ストアドプロシージャ、厳密なデータベースレベルの制約が必要なチーム
初期段階のプロジェクトでは、データベース・API・認証・ファイルストレージをすべてカバーする約30MBのバイナリが、本来であれば個別に立ち上げてメンテナンスしなければならない4つのサービスを置き換えます。これは十分に価値あるトレードオフです。

