メインコンテンツまでスキップ

第27章:DBに繋ぐ前の準備(接続文字列の考え方)🧵

この章は「DB接続がうまくいかない😭」の 8割を事前に潰す 章だよ〜!💪🐣 まだDBには繋がないけど、接続文字列(Connection String / DB URL)を“迷わず作れる・読める” ようにするよ!🚀


1) 接続文字列って結局なに?🤔➡️「DBの住所+鍵+オプション」🔑🏠

一言でいうと、DBに行くためのURL みたいなもの!🌐✨ (例:PostgreSQLだとこんな形)

  • 例(PostgreSQL) postgresql://ユーザー:パスワード@ホスト:ポート/DB名?オプション=値

この “形” 自体は、PostgreSQL公式の接続URI仕様に沿ってるよ。(PostgreSQL)


2) まずは分解できるようになろう🔍🧩(ここが超大事!)

たとえばこう👇(見た目はゴチャつくけど、部品は少ない

  • スキーム(種類): postgresql://(または postgres://)(PostgreSQL 日本)
  • ユーザー名: user
  • パスワード: pass
  • ホスト: host(どこにあるDB?)
  • ポート: 5432(入口番号)
  • DB名: mydb
  • クエリ(追加オプション): ?sslmode=require など(必要な時だけ)(Prisma)

3) 初心者が一番ハマるのは「hostは何を書くの?」問題🪤😵‍💫

ここだけ先に結論!📌✨ “API(あなたのNode/TS)がどこで動くか” で変わるよ👇

パターンA:APIがホスト(Windows)で動く 🪟➡️DBはどこ?

  • DBが同じPCで動く(例:WindowsにDB)なら host は localhost になりがち👍

パターンB:APIもDBもコンテナ 🐳🐳(次章以降の王道)

  • host は DBコンテナのサービス名(例:db) になる(Composeで自然にそうなる)🧩✨ ※「IP直書きしない」が正義🫶(前章の“名前解決”の続きだね!)

パターンC:APIはコンテナ、DBはホスト(Windows側)🪟🐳

  • 開発中なら host.docker.internal が便利なことが多いよ👍 これは Docker Desktop が用意してくれる “特別な名前” で、開発用途向け(本番のLinuxサーバ等では基本そのまま使えない)って注意があるよ。(Docker ドキュメント)

4) 接続文字列は「環境変数」に逃がす🎚️🌱(コードに直書きしない!)

理由はシンプル👇

  • パスワードをコードに書くと、うっかりGitに入る😱🧨
  • 環境ごと(開発/本番)に切り替えが大変😵
  • Composeでもクラウドでも、環境変数が基本ムーブ🧩✨

5) ハンズオン:まずは「接続文字列を環境変数化」して、分解チェックする✅🔍

ここでは “繋がらない前提で、文字列が正しいか検査” だけやるよ!😄 (次の章で “疎通がダメな時のチェック” に繋がる!🔗)

5-1. .env を作る📝✨

プロジェクト直下に .env を作って、DATABASE_URL を置く(例はPostgreSQL)👇

## .env(例:APIがホストで動いていて、DBがホストの想定)
DATABASE_URL=postgresql://todo_user:todo_pass@localhost:5432/todo_db

※ DBをDockerで動かして、APIもDockerになるなら host は localhost じゃなくなるよ(上のパターンB)🧠✨


5-2. .env.example も作る(超おすすめ)📦💡

## .env.example(Gitに入れてOKな“雛形”)
DATABASE_URL=postgresql://USER:PASSWORD@HOST:5432/DBNAME

そして .gitignore に .env を入れておく(もう入ってるならOK)🧹

.env

5-3. Nodeで「URLとして正しく読めるか」チェックする👀🧪

dotenv を入れる(すでに入ってたらスキップでOK)📦

npm i dotenv

src/dev/printDbUrl.ts を作る👇

import 'dotenv/config'

function mask(s: string | null | undefined) {
if (!s) return '(none)'
return s.length <= 2 ? '**' : s[0] + '*'.repeat(Math.max(1, s.length - 2)) + s[s.length - 1]
}

const raw = process.env.DATABASE_URL
if (!raw) {
console.error('❌ DATABASE_URL が未設定だよ! .env を確認してね')
process.exit(1)
}

let u: URL
try {
u = new URL(raw)
} catch (e) {
console.error('❌ DATABASE_URL が URL として壊れてるかも!')
console.error(' ありがち:パスワードに @ / : などが入っててURLが崩れる')
console.error(' → URLエンコード(%xx)を検討してね')
throw e
}

const dbName = u.pathname.replace(/^\//, '') || '(empty)'

console.log('✅ DATABASE_URL 解析結果')
console.log(' scheme :', u.protocol)
console.log(' user :', mask(u.username))
console.log(' password :', mask(u.password))
console.log(' host :', u.hostname)
console.log(' port :', u.port || '(default)')
console.log(' dbname :', dbName)
console.log(' params :', u.search || '(none)')

// 最低限チェック
const missing = []
if (!u.hostname) missing.push('host')
if (!dbName) missing.push('dbname')
if (missing.length) {
console.log('⚠️ 足りない項目があるかも:', missing.join(', '))
}

package.json にスクリプトを足す👇

{
"scripts": {
"dev:dburl": "node --loader ts-node/esm src/dev/printDbUrl.ts"
}
}

ts-node の構成は人によって違うので、もしここが合わなければ「今のプロジェクトのTS実行方法」に合わせてOKだよ😊 目的は “DATABASE_URL を new URL() で解析できる” を確認すること!🎯

実行👇

npm run dev:dburl

6) よくある落とし穴ランキング🏆🪤(ここだけで事故が減る!)

① パスワードに記号が入ってURLが壊れる🔐💥

URLには “予約文字” があるから、混ざると壊れることがあるよ😵 必要なら %エンコード(URLエンコード)する! MySQLの公式ドキュメントでも、URL中の予約文字はパーセントエンコードが必要って注意があるよ。(MySQL)

さらに嫌な話だけど、壊れたURLをそのまま例外ログに出すと 認証情報がログに出ちゃう 可能性もあるので、例外処理は丁寧にね😱🧯(GitHub)

② “localhost” の意味が変わる(ホスト vs コンテナ)🔁😵

  • ホストで動くアプリの localhost:ホスト自身
  • コンテナで動くアプリの localhost:コンテナ自身(別物!)

③ APIとDBが両方コンテナなのに host=localhost にしてる🐳❌

こういう時はだいたい host は db みたいなサービス名になる(次の章でガッツリやる!)🧩✨

④ Docker Desktop の host.docker.internal を本番でも使えると思う🚨

開発では便利だけど、Docker Desktop外(本番サーバ等)では前提が変わりやすいよ⚠️ “開発用途向け” って明記があるので、用途を分けようね😊(Docker ドキュメント)

⑤ Composeの環境変数が「どれが勝つか」混乱する🎚️😵

同じ変数が複数箇所にあると、優先順位があるよ(公式が順番を説明してる)📚(Docker Documentation) さらに env_file は optional にできる(最近のComposeの改善点)ってのも覚えておくと便利!(Docker Documentation)


7) Todo APIに向けた“小さな設計”🧱🌱(超かんたん版)

接続文字列は、アプリ内で 1か所だけ から読むのがおすすめ!📌✨

  • src/config/db.ts(みたいな場所)で

    • DATABASE_URL を読む
    • 無ければわかりやすく落とす
    • ログに “生パスワード” を出さない

これだけで、将来Composeやクラウドに行ってもラクになるよ😆🚀


8) AI活用(コピペでOK)🤖✨

接続文字列テンプレを作らせる📝

  • 「PostgreSQLのDATABASE_URLのテンプレを作って。user/pass/host/port/dbname をプレースホルダにして、例も2つ(localhost用、dbサービス名用)つけて」

今あるDATABASE_URLを“分解して説明”させる🔍

  • 「このDATABASE_URLを、scheme/user/password/host/port/dbname/params に分解して、間違いがありそうなら指摘して:(ここに貼る)」

記号入りパスワード対策を聞く🔐

  • 「DATABASE_URLのパスワードに @ や : が入るとき、どこをURLエンコードすべき?例も出して」

9) ミニクイズ(3問)🎓✨

  1. APIがコンテナ、DBもコンテナ のとき、host は何になりがち?🤔 → サービス名(例:db) 🧩

  2. host.docker.internal はいつでも使える?🤔 → Docker Desktopの開発用途で便利。本番では前提が変わることが多い⚠️(Docker ドキュメント)

  3. DATABASE_URL が壊れやすい原因トップは?🤔 → パスワードの記号でURLが崩れる(必要なら%エンコード)🔐💥(MySQL)


次の章へのつながり🔗😄

この章で「接続文字列の部品」がわかったから、次は “繋がらない時にどこから疑う?” を固定化していくよ!🔍✅(第28章へGO〜!🚀)