.envファイルとは?環境変数の基本と安全な管理方法
.env ファイルは、アプリごとに変わる設定値や秘密情報をコード本体から切り離して管理するためのファイルです。APIキー、データベース接続先、ポート番号のように、環境ごとに値が変わるものをまとめるときに使います。
実務で重要なのは、.env を「便利な設定ファイル」として雑に置くことではありません。公開してはいけない値をコードやGitに混ぜないこと、そして本番では .env 以外の仕組みも使い分けることです。ここを外すと、設定ミスより先に情報漏えいが起きます。
.envでできること: 開発環境ごとの差分をコードから分離できる- よく使う場面: ローカル開発、チーム開発、Docker実行、フレームワーク初期設定
- まず押さえる結論: 秘密情報を直書きしない、
.envをそのまま公開しない、公開側アプリでは秘密を置かない - この記事の例: 主に Node.js / Next.js / Docker / GitHub Actions を想定
ここがポイント:
.envは「秘密を安全にしてくれる魔法の箱」ではありません。安全性は、Git無視、公開範囲の分離、CI/CDのSecrets管理まで含めて初めて成立します。
.env ファイルと環境変数の関係
最初に区別したいのは、.env と環境変数は同じものではない、という点です。
環境変数は、OSや実行プロセスが持つ KEY=VALUE 形式の値です。アプリはそれを process.env などを通じて読み取ります。.env は、その環境変数をファイルとして書いておき、起動時に読み込むための補助的な仕組みです。
たとえば次のような設定は、コードに埋め込まず環境変数に向いています。
DATABASE_URLAPI_KEYAPP_ENVPORTLOG_LEVEL
12-Factor App でも、デプロイごとに変わる設定はコードから分離して環境で管理する考え方が示されています。これは、開発用と本番用で値が違う現場ほど効きます。
.env が向いている値、向いていない値
向いている値
- 環境ごとに変わる接続先
- APIキーやトークン
- ポート番号、ホスト名
- 機能フラグ
向いていない値
- 固定の業務ロジック
- 大きな設定構造体を丸ごと置く運用
- フロントエンドで隠したい秘密情報
後者を .env に寄せすぎると、設定の見通しが悪くなります。.env は万能な設定保管庫ではなく、変動する値の置き場所として使うのが基本です。
基本の書き方と最小例
Node.js の公式ドキュメントでは、.env はキーと値の組を1行ずつ書く形式として説明されています。Node.js には独自の .env 仕様もありますが、実務では多くのツールが似た形式を使います。
まずは最小例です。
APP_ENV=development
PORT=3000
DATABASE_URL=postgres://user:password@localhost:5432/sampledb
API_KEY=example_key_123
JavaScript 側では次のように読みます。
console.log(process.env.APP_ENV)
console.log(process.env.PORT)
想定される出力例です。
development
3000
命名ルールの目安
よく使われる書き方は次の通りです。
- 変数名は大文字のスネークケース:
DATABASE_URL - 値は
=の右側に書く - コメントは
#で始める - 意味が曖昧な短縮名は避ける
NG例も見ておくと実務で崩れにくくなります。
x=1
pass=abc123
url=localhost
これより、役割が分かる形のほうが安全です。
APP_PORT=3000
DB_PASSWORD=abc123
API_BASE_URL=http://localhost:8080
Node.js での読み込み方法
Node.js では、process.env で環境変数を参照できます。さらに、Node.js 20.6.0 で --env-file が追加され、最近のバージョンでは .env を標準機能で読み込みやすくなっています。
もっとも簡単な実行例
.env:
PORT=3000
APP_NAME=sample-app
app.js:
console.log(`name=${process.env.APP_NAME}`)
console.log(`port=${process.env.PORT}`)
実行コマンド:
node --env-file=.env app.js
出力例:
name=sample-app
port=3000
複数ファイルの読み込み
環境ごとの差分を分けたいなら、複数の --env-file を使えます。
node --env-file=.env --env-file=.env.development app.js
Node.js 公式では、後から指定したファイルが先の値を上書きします。また、同じ変数がOS側の環境変数にもある場合は、環境側の値が優先されます。
このルールを知らないまま調査すると、「.env を直したのに値が変わらない」という初歩的な詰まり方をしやすいです。
よくあるファイル構成
運用で使いやすいのは、役割ごとにファイルを分ける形です。
.env
.env.local
.env.development
.env.production
.env.example
それぞれの役割
.env: 共通の既定値.env.local: 各開発者のローカル上書き.env.development: 開発環境用.env.production: 本番用の設定名の整理用.env.example: 配布用の見本。秘密の実値は入れない
特に重要なのが .env.example です。新しく参加した人が必要な設定名を把握でき、値だけ自分で埋めれば動かせます。
例:
APP_ENV=
PORT=
DATABASE_URL=
API_KEY=
実務での使いどころ
概念だけだと使い分けが曖昧になるので、場面ごとに整理します。
ローカル開発
もっとも典型的です。各自のPCで接続先やAPIキーが違っても、コードを変えずに実行できます。
- 開発者AはローカルDBへ接続
- 開発者Bは検証用APIへ接続
- アプリ本体のコードは同じ
ステージングと本番の切り替え
同じアプリでも、URLや認証情報は環境ごとに違います。
- ステージング: テスト用DB、開発者向け通知
- 本番: 本番DB、本番通知先、監視設定あり
この差分をコードの if で埋めるより、環境変数として切り出したほうが管理しやすくなります。
Docker 実行
Docker は --env-file や Compose の env_file で環境変数を読み込めます。ただし Docker Docs では、パスワードのような機密情報を環境変数でコンテナに渡すより secrets を使うべきと明示しています。
つまり、ローカル開発では .env、本番寄りでは secrets という切り分けが現実的です。
Next.js やフロントエンドでの注意点
ここは誤解が多い部分です。フロントエンド系では、.env に書いたから安全になるわけではありません。
Next.js では NEXT_PUBLIC_ で始まる変数はブラウザ側に公開されます。つまり、次のような値は公開対象です。
NEXT_PUBLIC_API_BASE_URL=https://example.com
一方で、秘密にしたい値は NEXT_PUBLIC_ を付けず、サーバー側だけで使う必要があります。
STRIPE_SECRET_KEY=...
フロントエンドでやってはいけないこと
- 公開バンドルに入る変数へAPIシークレットを書く
- 「
.envにあるから見えないはず」と思い込む - クライアント側コードで秘密鍵を参照する
Next.js の公式でも、ブラウザに束ねられるのは NEXT_PUBLIC_ の付いた変数だと明記されています。公開アプリでは、どの値がブラウザへ出るかを名前で見分ける癖が必要です。
安全に管理するための基本ルール
ここがこの記事の本題です。.env の事故は、文法より運用で起きます。
1. .env をGitにコミットしない
最低限、.gitignore に入れます。
.env
.env.*
!.env.example
ただし、この書き方を採用するなら、共有したい .env.production などを本当に除外してよいかはチームで決めてください。無条件で広く除外すると、必要なテンプレートまで消えます。
2. 実値ではなく .env.example を共有する
チームへ渡すのは「項目名の一覧」です。実際の値は共有チャットに貼らず、パスワードマネージャーやSecrets機能で渡します。
3. 本番はSecrets管理を使う
GitHub Actions なら Secrets が使えます。リポジトリ、環境、組織単位で保持でき、ワークフローから明示的に参照します。
.env をそのままリポジトリに置く運用より、漏えい面でも権限面でもこちらが適切です。
4. ログに出さない
デバッグ中に次のようなコードを書くと、秘密情報がそのまま出ます。
console.log(process.env)
一時的でも避けるべきです。必要なら、キー名だけ出す、マスクする、長さだけ確認する、といった方法に変えます。
5. 使い終わったキーはローテーションする
一度でも誤って公開したら、.gitignore に追加して終わりではありません。すでに履歴やログへ残っている可能性があるため、値自体を再発行する必要があります。
よくある失敗と対処法
初心者が詰まりやすい点はかなり共通しています。
変数名を変えたのに反映されない
原因として多いもの:
- 開発サーバーを再起動していない
- 既存の環境変数が優先されている
- 別の
.env.*が上書きしている
確認ポイント:
- 実行し直したか
- シェルで同名の環境変数を
exportしていないか - フレームワークの読み込み順を確認したか
.env を置いたのに読まれない
原因として多いもの:
- ファイルの置き場所が違う
- ツール側が自動読込しない
- ファイル名が期待と違う
Next.js では .env* はプロジェクトルート基準です。src 配下に置いても読まれません。Node.js でも --env-file を付けなければ、自動では読み込みません。
数値や真偽値だと思っていたら文字列だった
環境変数は基本的に文字列です。たとえば次はそのままだと文字列です。
PORT=3000
DEBUG=false
JavaScript 側では必要に応じて変換します。
const port = Number(process.env.PORT)
const debug = process.env.DEBUG === 'true'
ここを曖昧にすると、false のつもりが真扱いになる事故が起きます。
NG例から見る安全な改善
NG例1: コードへ秘密情報を直書きする
const apiKey = 'sk_live_xxxxx'
改善例:
const apiKey = process.env.API_KEY
意味が大きく違います。コード共有やレビューの時点で秘密が広がらなくなります。
NG例2: フロントエンド公開変数へ秘密を書く
NEXT_PUBLIC_STRIPE_SECRET_KEY=sk_live_xxxxx
改善例:
NEXT_PUBLIC_API_BASE_URL=https://example.com
STRIPE_SECRET_KEY=sk_live_xxxxx
公開してよい値と秘密を分離します。
NG例3: .env を共有ドライブやチャットへ平文で貼る
改善例:
- 項目名は
.env.exampleで共有 - 実値は Secrets 管理やパスワードマネージャーで配布
- 失効できる鍵は短命にする
代替手段と使い分け
.env だけで全部回そうとすると、どこかで無理が出ます。用途ごとに分けると整理しやすくなります。
.env が向く場面
- ローカル開発
- 小規模な検証環境
- サンプルアプリのセットアップ
Secrets管理が向く場面
- GitHub Actions
- クラウド上の本番環境
- 権限分離が必要なチーム運用
- 監査ログやローテーションが必要な案件
Docker secrets などが向く場面
- コンテナ運用で機密情報を安全に渡したい
- 環境変数に載せたくない値がある
.env は入口として非常に便利ですが、本番運用の終着点ではないと考えると判断しやすくなります。
まず試せる最小手順
最後に、手元で試すための最短手順をまとめます。
- プロジェクト直下に
.envを作る - 次の内容を書く
APP_NAME=my-sample
PORT=3000
app.jsを作る
console.log(process.env.APP_NAME)
console.log(process.env.PORT)
- Node.js 20.6.0 以降で実行する
node --env-file=.env app.js
.gitignoreに.envを追加する- チーム共有用に
.env.exampleを作る
これだけで、.env の役割と基本的な安全運用はひと通りつかめます。次に見るべき点は、自分のプロジェクトでどこまでを .env に置き、どこからSecrets管理へ切り替えるかです。ここを曖昧にしないことが、実務では一番効きます。
参照リンク
- Node.js Docs: Environment Variables
- Node.js Learn: How to read environment variables from Node.js
- Node.js Docs: Command-line API
- The Twelve-Factor App: Config
- Next.js Docs: How to use environment variables in Next.js
- Docker Docs: docker container run
- Docker Docs: Set environment variables
- GitHub Docs: About secrets
- GitHub Docs: Using secrets in GitHub Actions
