第25章:“環境変数で初期化”の設計:最小で安全に🎛️
この章でやることはシンプル!👇 「初期化に必要な値(DB名・ユーザー名・パスワードなど)を、コードやSQLにベタ書きしないで、環境変数(+必要ならsecrets)で渡せる設計」にします 😎📦
1) まず結論:envに入れるのは「変えたい設定」だけ🧠🧩
環境変数に全部入れ始めると、すぐ事故ります🫠 なので、最初はこの2分類でOK👇
✅ envに入れてよい(= 設定・構成)
- DBホスト(例:
db) - DBポート(例:
5432) - DB名(例:
app) - 実行モード(例:
NODE_ENV=development) - ログレベルなど
🚫 envに入れると事故りやすい(= 秘密)
- DBパスワード
- APIキー
- JWT秘密鍵
- OAuthクライアントシークレット
秘密をenvに入れると、ログやエラー表示、AI貼り付け、画面共有で漏れる確率が上がります😱🧨 そこで次の章(この章の後半)で Compose secrets を使う「最小の安全策」も入れます🔒✨(secretsはコンテナ内でファイルとして渡せます)(Docker Documentation)
2) Composeには「環境変数の入口」が3つある📮📦📦📦
ここ、初心者が一番混乱するところなので、先に“地図”を置きます🗺️😆
A. .env(プロジェクト直下のやつ)
- これは主に **compose.yaml内の
${VAR}展開(interpolation)**に使われる用途です🧩 - 「コンテナへ入る環境変数」とは別物になりがち(混ぜると混乱)😵💫
- 何が展開に使われたかは
docker compose config --environmentで確認できます🔎(Docker Documentation)
B. env_file:(サービスに読み込ませるenvファイル)
- これは コンテナに環境変数を入れる用途📦
- 複数指定した場合、後ろのファイルが勝つ(上書き)🧯(matsuand.github.io)
C. environment:(compose.yamlに直書き)
- これも コンテナに環境変数を入れる用途📦
env_fileより強い(上書き)ので、最後の微調整だけに使うのが安全👍(Docker Documentation)
さらに、同じ変数が複数箇所にあるときの優先順位(どれが勝つ?)も公式で整理されています🧠 「なんで値が変わるの!?」ってなったら、ここが犯人です🕵️♂️(Docker Documentation)
3) “初期化で必要なenv”は、DB側とアプリ側で分ける✂️🐘🧑💻
例としてPostgreSQLで説明します🐘
公式イメージは、初回起動時に initdb をして、その後 /docker-entrypoint-initdb.d のSQLやシェルを実行して初期化できます🌱(hub.docker.com)
🐘 DBコンテナ(初期化用)でよく使うenv
POSTGRES_DBPOSTGRES_USERPOSTGRES_PASSWORD(これが要。必須扱い)(GitHub)
🧑💻 アプリコンテナ(接続用)でよく使うenv
DB_HOSTDB_PORTDB_NAMEDB_USERDB_PASSWORD(ただし後で secrets へ逃がすのが安全🔒)
4) まずは「最小で安全」なファイル構成にする📁✨
おすすめはこれ👇(混乱が減って、チームでも強い)
.env… compose.yamlの展開専用(秘密を入れない)env/app.env… アプリ用(コンテナに入れる)env/db.env… DB用(コンテナに入れる)secrets/… 秘密(ファイルで渡す)
コツ:
.envを「展開専用」にすると、頭がバグらない🧠✨ 逆に「.envを全部に使う」は便利そうに見えて、数日後に混乱して泣きます🥲
5) Compose例(env_file + secrets)🧩🔒
✅ compose.yaml(例)
services:
db:
image: ${POSTGRES_IMAGE}
env_file:
- ./env/db.env
secrets:
- db_password
volumes:
- db-data:/var/lib/postgresql/data
## 第25章:“環境変数で初期化”の設計:最小で安全に🎛️
# ports:
# - "5432:5432"
app:
build: .
env_file:
- ./env/app.env
secrets:
- db_password
depends_on:
- db
secrets:
db_password:
file: ./secrets/db_password.txt
volumes:
db-data:
- secretsはコンテナ内で
/run/secrets/<secret_name>のファイルとして渡されます🔒(Docker Documentation) env_fileは「コンテナに入れるenv」用途です📦(Docker Documentation).envは${POSTGRES_IMAGE}みたいな compose.yaml内の展開に使えます🧩(Docker Documentation)
✅ .env(展開専用:秘密入れない)
POSTGRES_IMAGE=postgres:latest
✅ env/db.env(DB初期化用:ユーザーとDB名だけ)
POSTGRES_DB=app
POSTGRES_USER=appuser
## パスワードは secrets に逃がす(ここには書かない)
✅ env/app.env(アプリ接続用:パスワードは secrets から読む)
DB_HOST=db
DB_PORT=5432
DB_NAME=app
DB_USER=appuser
6) TypeScript側:環境変数チェック&secrets対応(最小)🧪✅
「動かない理由がわからない」を潰す最強手段は、起動直後に設定チェックして落ちることです💥(落ち方が親切になる)
// src/config.ts
import fs from "node:fs";
function must(name: string): string {
const v = process.env[name];
if (!v) throw new Error(`Missing env: ${name}`);
return v;
}
function readSecretIfExists(path: string): string | null {
try {
return fs.readFileSync(path, "utf8").trim();
} catch {
return null;
}
}
const DB_PASSWORD =
readSecretIfExists("/run/secrets/db_password") ?? process.env.DB_PASSWORD;
if (!DB_PASSWORD) {
throw new Error("Missing DB password (secret or env DB_PASSWORD)");
}
export const config = {
db: {
host: must("DB_HOST"),
port: Number(must("DB_PORT")),
name: must("DB_NAME"),
user: must("DB_USER"),
password: DB_PASSWORD,
},
};
// 事故防止:ログにパスワードは出さないこと🙅♂️
これで、
- secretsがあるなら secrets を使う🔒
- なければ env にフォールバック(ローカル緊急用)🧯 ができます✨
7) 事故あるある集(ここが地雷)💣🤣
💥 あるある1:.env に書いたのに反映されない
→ それ、コンテナ用じゃなくて展開用だった可能性大です😵💫
.env は主に ${VAR} 展開(interpolation)向けです🧩(Docker Documentation)
✅ 対策:
- コンテナへ入れるのは
env_fileorenvironment - 展開に使われた値は
docker compose config --environmentで確認🔎(Docker Documentation)
💥 あるある2:同じ変数が複数箇所にあって、どれが勝ってるかわからない
→ 公式の優先順位ルールがまさにこれです🕵️♂️
(shellの環境変数が勝ったり、environment: が勝ったり)(Docker Documentation)
✅ 対策:
- 変数の置き場所を減らす(最小に)✂️
- “最後に勝つ場所” を1つだけにする(おすすめは
env_fileに寄せる)📦
💥 あるある3:パスワードをenvに入れてAIに貼ってしまう
→ これ、最も多い漏えいパターンです😱 ✅ 対策:
- 秘密は secrets(ファイル)へ🔒(Docker Documentation)
- AIに投げるときは、値を
***に置換してから🤖🛡️
8) 今日のミニ課題(10〜15分)⏱️🎮
課題A:構成を分離してみよう📁
.envはPOSTGRES_IMAGEだけにするenv/db.envにPOSTGRES_DB,POSTGRES_USERを入れるsecrets/db_password.txtを作って secrets で渡すdocker compose up -dで起動!
課題B:反映チェック🔎
docker compose config --environment を実行して、展開に使われた値を見てみよう!(Docker Documentation)
9) AIの使い方(安全版)🤖🛡️✨
- ✅ 「env設計メモ」を貼って、“この変数は設定?秘密?” の分類を出してもらう
- ✅
compose.yamlの雛形を作ってもらう(値はダミーにする) - ✅ 起動エラー文(秘密は伏せる)から原因候補を3つ出させる
🚫 ダメ:本物のパスワード/APIキーを貼る🔐❌
まとめ:第25章のゴール🏁🎉
- envは「設定」、secretsは「秘密」🔒
.env(展開)とenv_file(コンテナ)は役割が違う🧩- 迷ったら
docker compose config --environmentで確認🔎(Docker Documentation) - PostgreSQLの初期化は “初回にenv + init scripts” が基本形🌱(hub.docker.com)
次の章に進むなら、ここで作った構成をベースに「Windowsで重いときの逃げ道」に繋げると、開発体験が一気に良くなります🐢➡️🐇✨