Day8:Docker Compose × 環境変数で「設定をコードから切り離す」
Day8のテーマは、Docker Compose に 環境変数(environment variables) を組み合わせて、設定値をきれいに管理することです。
ここを押さえると、パスワードや接続情報を「コードにベタ書きしない」という、実務では当たり前の設計に一気に近づきます。
環境変数は、アプリに「外から渡す設定」です。
Docker Compose は、この環境変数をとても扱いやすい形でサポートしてくれます。
まずは完成イメージ:Compose + 環境変数付き Web + DB
次のような docker-compose.yml をイメージしてください。
version: "3"
services:
web:
build: .
ports:
- "3000:3000"
environment:
- DB_HOST=db
- DB_USER=myuser
- DB_PASSWORD=${DB_PASSWORD}
depends_on:
- db
db:
image: mysql:8
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_DATABASE: myapp
YAMLそして、同じディレクトリに .env ファイルを置きます。
DB_PASSWORD=super-secret-password
この構成で、
パスワードはコードにもComposeファイルにも直書きされず、.env にだけ書かれる状態になります。
ここから、環境変数まわりを丁寧に分解していきます。
Composeにおける environment: の基本
services.web.environment の意味
web:
environment:
- DB_HOST=db
- DB_USER=myuser
- DB_PASSWORD=${DB_PASSWORD}
YAMLここで書いているのは、
「web コンテナの中に、これらの環境変数をセットして起動してね」という指示です。
コンテナの中から見ると、
次のような状態になっています。
DB_HOST という環境変数に db が入っている。
DB_USER に myuser が入っている。
DB_PASSWORD には .env から読み込まれた値が入っている。
Node.js なら process.env.DB_HOST、
Python なら os.getenv("DB_HOST") のようにして、
アプリ側から参照できます。
コードの中に
「host: ‘db’」
「password: ‘super-secret-password’」
と書くのではなく、
環境変数から読むようにするのが実務的な書き方です。
${DB_PASSWORD} の意味と .env ファイルの役割
変数展開としての ${…}
Composeファイルの中で ${DB_PASSWORD} と書くと、
「DB_PASSWORD という名前の環境変数の値をここに差し込んでね」という意味になります。
この値はどこから来るかというと、
同じディレクトリにある .env ファイルです。
.env ファイルの中身
DB_PASSWORD=super-secret-password
この一行で、
Composeは DB_PASSWORD という名前の変数に
super-secret-password をセットします。
その結果、
Composeファイルの ${DB_PASSWORD} の部分が
実行時に super-secret-password に置き換わります。
これにより、
パスワードを Composeファイルに直書きせずに済みます。
dbサービス側の環境変数と連携する
MySQL公式イメージが期待する環境変数
db:
image: mysql:8
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_DATABASE: myapp
YAMLMySQL の公式イメージは、MYSQL_ROOT_PASSWORD や MYSQL_DATABASE といった環境変数を読むことで、
初期設定を自動で行います。
ここで ${DB_PASSWORD} を使うことで、
web と db の両方が同じパスワードを共有できます。
web は DB_PASSWORD として、
db は MYSQL_ROOT_PASSWORD として、
それぞれ別の名前で受け取っていますが、
元の値は .env の DB_PASSWORD です。
これにより、
「パスワードを一箇所で管理する」
という状態が作れます。
コード側から環境変数を読むイメージ
Node.js の例
Node.js で MySQL に接続するコードは、例えばこうなります。
const mysql = require("mysql2");
const connection = mysql.createConnection({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: "myapp",
});
JavaScriptここで、process.env.DB_HOST には db が入り、process.env.DB_USER には myuser が入り、process.env.DB_PASSWORD には .env の値が入ります。
コード側は「環境変数から読む」という前提だけを持ち、
具体的な値は Compose と .env に任せる。
これが「設定をコードから切り離す」という設計です。
セキュリティ視点から見た環境変数管理
なぜコードにパスワードを書いてはいけないのか
コードにパスワードを書いてしまうと、
Git にコミットされたり、
レビューで丸見えになったり、
別プロジェクトにコピペされたりと、
漏洩リスクが一気に高まります。
環境変数を使うことで、
コードは「パスワードという概念」だけを扱い、
具体的な値は外部に逃がせます。
.env をどう扱うべきか
.env は基本的に Git にコミットしません。.gitignore に .env を追加しておき、
各開発者が自分の .env を持つ形にします。
本番環境では、.env ではなく、
インフラ側(CI/CDやオーケストレーションツール)で
環境変数を注入することが多いです。
Composeはその“練習版”としてちょうど良い位置づけです。
Compose + 環境変数の“実務的な型”を頭に入れる
典型的なパターン
Composeファイルには
「どの環境変数をコンテナに渡すか」だけを書く。
具体的な値は .env に書く。
アプリコードは process.env.XXX のようにして読む。
パスワードやAPIキーは、
コードにもComposeファイルにも直書きしない。
この型をそのまま真似するだけで、
設定管理のレベルが一段上がります。
Day8(Compose + 環境変数)のゴールの再確認
自分の言葉で、こう説明できればOKです。
Docker Compose では、
services の中の environment で
コンテナに渡す環境変数を定義できる。
値を ${VAR_NAME} と書くと、
同じディレクトリの .env ファイルから読み込まれる。
アプリ側は process.env.XXX などで環境変数を読み、
パスワードや接続情報をコードにベタ書きしなくて済む。
web と db の両方が、
同じ .env の値を別々の名前で共有できる。
ここまで腹落ちしていれば、
「Compose + 環境変数」は実務レベルで十分使える状態です。

