【Laravel】環境ごとの.env管理とシークレット情報の扱い方

laravelアイキャッチ Laravel

こんにちは、かつコーチです。

前回は、Laravelアプリを本番環境にデプロイする一連の流れを解説しました。

その手順の中で何度も登場した .env ファイルですが、実は「開発環境と本番環境でどう使い分けるか」「パスワードなどの機密情報をどう安全に扱うか」は、初めてデプロイする人がつまずきやすいポイントです。

今回は、この .env ファイルの環境ごとの管理方法と、シークレット情報の安全な取り扱い方を掘り下げていきます。

.env ファイルの役割をおさらいする

環境によって変わる設定を1箇所に集める

.env ファイルは、データベースの接続情報やAPIキーなど、環境によって値が変わる設定をまとめて管理するファイルです。

# .env の例
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
APP_DEBUG=true
APP_URL=http://localhost

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=

ソースコードの中に直接 password123 のような値を書いてしまうと、その値を変えるたびにコードを修正する必要が出てしまいます。

.env に切り出しておけば、環境ごとに違う値を設定でき、コード自体は一切変更せずに済みます。

.gitignore に含まれている理由

.env はLaravelの初期状態で .gitignore に登録されており、Gitの管理対象から外れています。

これは、データベースのパスワードやAPIキーといった機密情報が、そのままGitHubなどの公開リポジトリに載ってしまうのを防ぐためです。

代わりに、値の入っていない雛形として .env.example をリポジトリにコミットし、各環境でそれをコピーして値を埋める、という運用が基本になります。

環境ごとに .env を使い分ける

local / staging / production の違い

Laravelでは、APP_ENV の値によって「今どの環境で動いているか」を判定します。

環境APP_ENV用途
ローカル開発local自分のPC上での開発
ステージングstaging本番相当の環境で最終確認
本番production実際のユーザーが利用する環境

それぞれの環境ごとに、内容の異なる .env ファイルをサーバー側で個別に用意します。

# ローカルの.env(一部)
APP_ENV=local
APP_DEBUG=true
DB_HOST=127.0.0.1
DB_DATABASE=laravel_local

# 本番の.env(一部)
APP_ENV=production
APP_DEBUG=false
DB_HOST=db.internal.example.com
DB_DATABASE=laravel_production

重要なのは、この .env ファイル自体はどの環境でもGitの管理対象にせず、サーバーごとに直接配置する(またはCI/CDのシークレット機能経由で生成する)という点です。

APP_ENV を使ってコード側で環境判定する

.env の値は、コントローラやサービスクラスの中で app()->environment() を使って判定できます。

if (app()->environment('production')) {
    // 本番環境でのみ実行したい処理
    Log::channel('slack')->critical('重大なエラーが発生しました');
} else {
    // ローカルやステージングではログに出すだけ
    Log::debug('デバッグ情報');
}

「本番でだけ通知を飛ばす」「ローカルでだけデバッグ用のツールバーを表示する」といった環境依存の分岐は、この仕組みを使うのが基本です。

つまずきやすいポイント:.env を誤ってGitにコミットしてしまった経験

一度公開リポジトリに機密情報を上げてしまった話

私が実際にやってしまった大きな失敗が、.gitignore の設定前に一度だけ .env をコミットしてしまったことです。

❌ Before:.gitignore の設定を後回しにしてしまう

# プロジェクト作成直後、.gitignoreを確認せずにコミット
git init
git add .
git commit -m "initial commit"
git push origin main

このとき、.env の中にはローカル用とはいえデータベースのパスワードが書かれた状態のまま、リポジトリの履歴に残ってしまいました。

幸いプライベートリポジトリだったため実害はありませんでしたが、後から git log の履歴を確認して初めて気づき、青ざめた記憶があります。

✅ After:コミット前に .gitignoregit status を必ず確認する

git init

# .gitignoreに.envが含まれているか先に確認する
cat .gitignore | grep ".env"

# add前に何がステージされるか必ず確認する
git status

git add .
git commit -m "initial commit"

一度コミット履歴に混入した機密情報は、単に .env を削除するコミットを積んでも履歴には残り続けてしまいます。

この失敗以降、私は新規プロジェクトを作るたびに、最初のコミットの前に必ず git status.env がステージされていないことを確認するようにしています。

もし誤ってコミットしてしまった場合は、git filter-repo などで履歴自体から該当ファイルを除去したうえで、該当のパスワードやAPIキーは速やかに再発行することが必須です。

本番のシークレット情報を安全に配置する方法

サーバーに直接SCPで送る方法

もっともシンプルなのは、.env ファイルをサーバーに直接転送する方法です。

scp .env.production user@your-server:/var/www/your-app/.env

小規模なプロジェクトであれば、この方法でも十分実用的です。

CI/CDのシークレット機能を使う方法

前回のCI連携の記事で登場したGitHub Actionsには、機密情報を安全に扱うためのSecretsという機能があります。

GitHubリポジトリの「Settings > Secrets and variables > Actions」から登録した値は、ワークフローの中で ${{ secrets.名前 }} として参照できます。

- name: 本番サーバーに.envを生成
  run: |
    echo "APP_ENV=production" > .env
    echo "APP_KEY=${{ secrets.PROD_APP_KEY }}" >> .env
    echo "DB_PASSWORD=${{ secrets.PROD_DB_PASSWORD }}" >> .env

Secretsに登録された値は暗号化されて保存され、ログにも自動的にマスクされて表示されるため、GitHub Actionsの実行ログを誰かが見ても値そのものは分かりません。

クラウドのシークレット管理サービスを使う方法

AWSやGCPを使う場合は、AWS Secrets ManagerやGoogle Secret Managerといった専用のサービスに機密情報を保管し、アプリ起動時に取得する構成もよく使われます。

規模が大きくなるほど、.env ファイル単体で管理するよりも、こうした専用サービスに一元化した方が、アクセス権限の管理やローテーション(定期的な値の更新)がしやすくなります。

応用:.env に頼りすぎない設計

設定値はできるだけ config/ 経由で参照する

Laravelのベストプラクティスとして、コントローラやサービスクラスの中で env() 関数を直接呼び出すのは推奨されていません。

// ❌ Before:env()を直接呼び出す
$apiKey = env('STRIPE_API_KEY');

// ✅ After:config/経由で取得する
$apiKey = config('services.stripe.key');
// config/services.php
return [
    'stripe' => [
        'key' => env('STRIPE_API_KEY'),
    ],
];

理由は、次回解説する config:cache を実行すると、キャッシュされた設定ファイルからは .env の値が読み込まれなくなるためです。

config/ の設定ファイル経由で一度値を受け取るようにしておけば、キャッシュを使った本番運用でも正しく値が反映されます。

まとめ

この記事のポイント

  • .env は環境によって変わる設定をまとめる仕組みで、.gitignore によりGit管理から除外するのが基本
  • APP_ENV の値(local / staging / production)で環境ごとの挙動をコード側で分岐できる
  • 一度Gitにコミットした機密情報は履歴に残り続けるため、コミット前の git status 確認が重要
  • 本番のシークレットは、SCPでの直接転送、CI/CDのSecrets機能、クラウドのシークレット管理サービスなど規模に応じて選ぶ
  • env() の直接呼び出しは避け、config/ の設定ファイル経由で値を参照するのがベストプラクティス

次に読むべき記事

環境変数の扱い方を理解したところで、次はその config:cache を含めた「Laravelのキャッシュ設定」について詳しく見ていきます。

→ 次の記事:Laravelのキャッシュ設定(config/route/viewキャッシュ)

タイトルとURLをコピーしました