なぜデータベースの章か
このサーバー編の根底に、一つの思想が流れている。サーバー本体は作り直せる。作り直せないのは、データだけだ。 OSが壊れても入れ直せる。設定ファイルは書き直せる。アプリは再インストールできる。だが、あなたが三年かけて貯めた家計の記録、家族の写真、仕事のメモ——それは一度失えば戻らない。この思想は第10章で全面的に展開するが、その前にどうしても済ませておくべきことがある。データの置き場所を、土台として設計することだ。
そしてもう一つ。写真はあのクラウド、家計簿は別のアプリ、メモはまた別のサービス——気づけば自分の暮らしのデータは、いくつもの他社のサーバーにバラバラに預けられている。データを他社のクラウドサービスに散らばせたままでは、主導権は戻らない。自分の機械の上の、自分のデータベースに集める。 これが、第1章で確認した「データ主権」を、具体的な形にする一歩だ。
では、ファイルの山とデータベースは何が違うのか。CSV、スプレッドシート、あちこちのテキストファイル——それらでもデータは持てる。だが、量が増え、複数の場所から触り始めると壁にぶつかる。「先月の食費の合計は?」を一発で出せるか(検索)。同じ品目を二重に登録していないか(整合性)。二つのアプリが同時に書き込んで壊れないか(同時アクセス)。データベースは、これらを最初から面倒見るために作られた、「構造を持ったデータ」の置き場だ。
この土台は、この先ずっと効く。第8章でFastAPIを使って建てる自作アプリも、第9章で外の世界に公開するサービスも、突き詰めればこのデータベースの上で動く。だから今、土台を据える。
第一節 SQLiteとPostgreSQLの使い分け
データベースと聞いてまず名前が挙がる二つが、SQLiteとPostgreSQLだ。だがこの二つは競合ではない。守備範囲が違う道具だ。どちらが上ということはなく、向き不向きがある。
SQLite は、データベース全体が一枚のファイルになる。notes.db というファイルが一つ、それがデータベースのすべてだ。サーバープロセスは要らない。設定もゼロ。apt install sqlite3 だけで使える。アプリの中に組み込んで動かすのが基本で、単一の書き込み主体・小規模・個人用のアプリに最適だ。地味に見えるが、実は世界で最も使われているデータベースでもある——あなたのスマホの中にも、ブラウザの中にも、無数のSQLiteが動いている。
PostgreSQL は、サービスとして常駐する本格的なデータベースだ。第6章で学んだ systemctl の世界の住人で、起動しっぱなしで接続を待ち受ける。複数のアプリ・複数のユーザーが同時に接続でき、誰が何をできるかの権限管理があり、ネットワーク越しにも繋げる。トランザクション(一連の操作を「全部やるか、全部やらないか」にまとめる仕組み)の堅牢さも本物だ。
どちらを選ぶか。判断の軸を表にする。
| 軸 | SQLite向き | PostgreSQL向き |
|---|---|---|
| 書き込むのは誰か | 自分のアプリ一つ | 複数のアプリ・人 |
| 同時アクセス | ほぼ単独 | 同時に多数 |
| データ量 | 小〜中規模 | 中〜大規模 |
| 権限を分けたいか | 不要 | 利用者ごとに分けたい |
| ネットワーク越しの接続 | 基本しない | する |
| 運用の手間 | ほぼゼロ | サービスとして管理 |
方針はこうだ。まずSQLite、育ったらPostgreSQL——これが自然な道だ。 小さく始めて、手に余ってきたら引っ越せばいい。ただし、このサーバー編では別の事情がある。サーバーには最初からPostgreSQLを入れて、触って慣れておく。 本番で必要になってから慌てて学ぶより、実験機のうちに手を動かしておくほうが断然いい。それをこの章の後半でやる。
まずはSQLiteを最小例で触ってみよう。土台を体で掴むためだ。
# SQLite を入れる(コマンドラインツール)
sudo apt install sqlite3
# ~/data/notes.db というデータベース(=一枚のファイル)を開く
mkdir -p ~/data
sqlite3 ~/data/notes.db
sqlite3 のプロンプトに入ったら、数行だけ打ってみる。
-- メモを入れるテーブルを作る
CREATE TABLE notes (id INTEGER PRIMARY KEY, body TEXT, created TEXT);
-- 一行入れる
INSERT INTO notes (body, created) VALUES ('最初のメモ', '2026-06-10');
-- 取り出す
SELECT * FROM notes;
-- テーブル一覧を見て、抜ける
.tables
.quit
.tables や .quit のようにドットで始まるのはSQLite独自の命令で、それ以外はSQLという共通言語だ。たったこれだけで、~/data/notes.db という一枚のファイルが立派なデータベースになっている。バックアップもコピーも、このファイル一つを扱えばいい——これがSQLiteの軽さだ。
Claudeに聞いてみよう①:SQLiteとPostgreSQLのどちらが向くか判定させる
私はDebian 13サーバーで、次のものを動かしたい・作りたいと考えています: 〔例:自分用の家計簿アプリ、家族で共有する蔵書リスト、勉強で作るWebアプリ、在庫管理……など、思いつくまま一覧で〕
それぞれについて、データの置き場所としてSQLiteとPostgreSQLのどちらが向くか、理由つきで判定してください。判断に使った軸(書き込む人の数・同時アクセス・権限分けの要否など)も明示してください。「最初はSQLite、育ったらPostgreSQL」が妥当なものがあれば、その移行の目安も添えてください。
最初に「自分の用途ではどちらか」を言葉にしておくと、この先の設計が楽になる。Claudeに判定させると、自分では迷っていたものに理由つきの線が引ける。
第二節 PostgreSQLを入れる
方針どおり、実験機にPostgreSQLを入れる。Debian 13(trixie)では、入るのは PostgreSQL 17 だ。
sudo apt install postgresql
ここで第6章が効いてくる。PostgreSQLは入れた瞬間からサービスとして動き出す。 だから確認は第6章の作法そのままだ。
systemctl status postgresql
Active: active と出ていれば、もう動いている。Debianでは、PostgreSQLは「クラスタ」という単位で管理される(複数バージョンを並べて持てる仕組みだ、とだけ掴んでおけばいい)。設定ファイルは /etc/postgresql/17/main/ の下にある。
# 設定ファイルの置き場所を覗く
ls /etc/postgresql/17/main/
最初の関門「peer認証」
入れた直後、psql といきなり打つと弾かれる。最初の関門が peer認証 だ。Debianの初期設定では、PostgreSQLの管理ユーザー postgres には、OSの postgres ユーザーになっているときだけ入れる。OS側のユーザー名とDB側のユーザー名を突き合わせて認証する仕組みで、これを peer認証と呼ぶ。だから最初の入口はこうなる。
# OSのpostgresユーザーとしてpsqlを起動する
sudo -u postgres psql
これで postgres=# というプロンプトに入れる。\q で抜けられる。
自分用のロールとDBを作る
postgres ユーザーで何でもやるのは行儀が悪い。第5章の「必要最小限の権限」の発想どおり、アプリ用のロール(ユーザー)と、専用のデータベースを作る。
# myapp というロールを作る(パスワードを対話的に設定)
sudo -u postgres createuser --pwprompt myapp
# myapp が所有する myappdb というデータベースを作る
sudo -u postgres createdb -O myapp myappdb
作ったら、myapp として接続できるか試す。
psql -h localhost -U myapp -d myappdb
-h localhost を付けると、peer認証ではなくパスワード認証になり、さっき設定したパスワードを聞かれる。これで自分専用のロールとDBの入口ができた。
守りの確認——どこに耳を開いているか
第5章で「攻撃面(公開している入口)を自分の目で確かめる」作法をやった。データベースでもそれをやる。PostgreSQLがどこからの接続を待ち受けているかを、自分の目で見る。
ss -tlnp | grep 5432
PostgreSQLのポートは 5432 だ。出力のアドレス欄が 127.0.0.1:5432 になっていれば、それは「同じ機械の中からしか繋げない」という意味だ。外の世界には耳を開いていない。
LISTEN 0 244 127.0.0.1:5432 0.0.0.0:* ...
これがDebianのPostgreSQLの初期状態で、外部公開はデフォルトでは閉じている。これは安全側の初期値だ。いつか別の機械から繋ぎたくなったら、/etc/postgresql/17/main/postgresql.conf の listen_addresses と pg_hba.conf をいじることになるが——開ける前に、まずClaudeと脅威モデルを相談する。 第5章で叩き込んだとおり、データベースを外に開けるのは重い決断だ。127.0.0.1 に閉じている限り、攻撃面はほぼゼロに保てる。
Claudeに聞いてみよう②:いまのPostgreSQLの状態を解説させる
私のDebian 13サーバーにPostgreSQL 17を入れたところです。状態を確認したら次の出力でした:
〔systemctl status postgresql の出力を貼る〕〔ss -tlnp | grep 5432 の出力を貼る〕いま私のPostgreSQLがどういう状態か、一つずつ解説してください。特に、どこからの接続を待ち受けているか(外部に開いているか・閉じているか)を、出力のどの部分から読み取れるか教えてください。この状態はセキュリティ上どう評価できますか。
status と ss の出力を両方貼るのがコツだ。「動いているか(status)」と「どこに開いているか(ss)」は別の問いで、Claudeは二つを突き合わせて、いまの守りの姿勢を読み取ってくれる。
第三節 最初のテーブルとSQLの入口
データベースの土台ができた。中に小さな実例を一つ作って、SQLの入口を覗く。題材は家計簿にしよう。
psql -h localhost -U myapp -d myappdb
myappdb=> のプロンプトに入ったら、テーブルを一つ作る。
-- 家計簿テーブル:日付・品目・金額
CREATE TABLE kakeibo (
id SERIAL PRIMARY KEY,
hizuke DATE NOT NULL,
himmoku TEXT NOT NULL,
kingaku INTEGER NOT NULL
);
-- 何行か入れてみる
INSERT INTO kakeibo (hizuke, himmoku, kingaku) VALUES
('2026-06-01', '米', 2800),
('2026-06-02', '野菜', 650),
('2026-06-03', '本', 1980);
-- 取り出す
SELECT * FROM kakeibo;
PostgreSQL独自の便利な命令も覚えておく。
\d kakeibo -- このテーブルの構造(スキーマ)を見る
\dt -- テーブルの一覧
\q -- 抜ける
SERIAL は「自動で連番を振る」型、DATE は日付、INTEGER は整数だ。NOT NULL は「空を許さない」という制約で、これがあるおかげで「金額の入っていない記録」が混ざらない——これが整合性の一例だ。
SQLは暗記する時代ではなく、Claudeに書かせて読む時代
ここで肝心なことを言う。SQLは暗記する時代ではなく、Claudeに書かせて読む時代だ。 「月ごとの合計」「品目別の集計」といった問い合わせは、SQLの文法を諳んじていなくても書ける。やり方は、テーブルの構造をClaudeに見せて、やりたいことを日本語で伝えるだけだ。
-- まず構造を見せるために、この出力を取る
\d kakeibo
その \d kakeibo の出力を貼って、「月ごとの合計を出すSQLを書いて、各句の意味も説明して」と頼む。返ってきたSQLは丸呑みせず、各句の意味を一度は読む——第6章の unit file と同じ、「書かせてレビューする」流儀だ。エラーが出たら、エラーメッセージをそのまま貼る。本編第8章のトラブルシュートで身につけた「ログをそのまま渡す」作法が、ここでも効く。
Claudeに聞いてみよう③:自分のデータのテーブルを設計させる
私はDebian 13サーバーのPostgreSQL 17で、次のデータを管理したいです: 〔例:読書記録(本のタイトル・著者・読了日・評価)、在庫(品名・数量・仕入れ日)、顧客メモ……など、自分が貯めたいデータ〕
このデータを入れるテーブルを設計してください。
CREATE TABLE文を書き、各カラムについて「なぜその型(TEXT / INTEGER / DATE / SERIAL など)を選んだか」を一つずつ説明してください。空を許さないほうがよいカラム(NOT NULL)があれば、その理由も添えてください。
テーブル設計は、データベースで最初にして最も効く判断だ。型の選び方をClaudeに説明させることで、「なぜこの形なのか」を自分で読めるようになる。一度やれば、次のテーブルは自分で当たりをつけられる。
第四節 データを守る入口
第10章への伏線を、ここで一つ張っておく。せっかくデータベースにデータを集めても、その守り方を間違えると、いざというとき壊れたバックアップしか手元にない、という最悪が起きる。
やってはいけないのは、稼働中のデータベースのファイルを直接コピーすることだ。PostgreSQLやSQLiteが書き込んでいる最中のファイルを cp で複製すると、書きかけの中途半端な状態が固定され、復元しようとしても壊れている——という危険な方法だ。正しい入口は、データベース自身に「バックアップ用の形」で吐き出させることだ。
# PostgreSQL:myappdb をテキスト(SQL文の集まり)として書き出す
pg_dump -h localhost -U myapp myappdb > ~/data/myappdb-backup.sql
# SQLite:稼働中でも安全な専用コマンドでコピーする
sqlite3 ~/data/notes.db ".backup ~/data/notes-backup.db"
pg_dump が吐くのはテキストだ。中身は CREATE TABLE や INSERT の並んだSQL文で、人が読めるし、gitで差分が取れるし、Claudeに貼って中身を確認することもできる。これがバイナリのコピーにはない強みだ。SQLiteの .backup は、ファイルを直接コピーする代わりに、書き込み中でも安全な状態でコピーを取ってくれる専用命令だ。
ここでは「正しい入口はこれだ」と手を動かすところまで。自動化(毎晩決まった時刻に・確実に取る)と、何より大事な「復元の演習」は、第10章で本格的にやる。 バックアップは取るだけでは半分で、戻せて初めて完成する——その話は次の次の章だ。
Claudeに聞いてみよう④:自分のDB構成のバックアップ手順を書かせる
私のDebian 13サーバーには、次のデータベースがあります: 〔例:PostgreSQL 17 の myappdb、SQLite の ~/data/notes.db〕
それぞれについて、壊れていない正しいバックアップを取る最小の手順を書いてください。稼働中のファイルを直接コピーしてはいけない理由も、初心者に分かるように一言添えてください。バックアップファイルの置き場所と命名の付け方も提案してください(日付を入れるなど)。
この④は任意だ。だが自分の構成を一度Claudeに渡しておくと、第10章で自動化に進むときの土台になる。
まとめ
この章でやったこと:
- 「作り直せないのはデータだけ」という思想から、データの置き場所を土台として設計する意味を確認した
- ファイルの山とデータベースの違い(検索・整合性・同時アクセス・構造を持ったデータ)を整理した
- SQLiteとPostgreSQLの守備範囲を表で分け、「まずSQLite、育ったらPostgreSQL」の方針を立てた
- SQLiteを一枚のファイルで触り、Debian 13にPostgreSQL 17を入れた
- peer認証を越え、自分用のロールとDBを作り、
ssで 127.0.0.1 にしか開いていないことを自分の目で確認した - 家計簿テーブルでSQLの入口を覗き、「Claudeに書かせて読む」型を身につけた
- 壊れないバックアップの正しい入口(
pg_dump/.backup)を手を動かして確認した
手元に残ったもの:
- 一枚のファイルになったSQLiteのデータベース(
~/data/notes.db) - サービスとして動くPostgreSQL 17と、自分専用のロール・データベース(
myapp/myappdb) - 「構造を持ったデータ」を扱う最初のテーブル(
kakeibo) \dの出力を渡してSQLを書かせる対話の型- 壊れないバックアップの取り方(第10章への入口)
データの土台ができた。OSもアプリも作り直せるが、いまこの土台に載せ始めたデータだけは作り直せない——その重みを抱えたまま、次に進む。次の第8章「自作アプリを動かす」では、この土台の上に、PythonとFastAPIで自分のアプリを建てる。ディレクトリ構成を決め、systemdのサービスとして動かすところまで、Claudeと一緒に進む。
シリーズ全体はClaudeと一緒に学ぶDebian サーバー編 一覧から辿れる。本編(デスクトップ編)は全章一覧へ。コメント・議論は Facebook グループへ:AISeed — 生物多様性・食料・AIと暮らし