はじめに
Web開発をしていると、こんな記述を見かけることがあります。
ENV["DATABASE_URL"]
import.meta.env.VITE_API_BASE_URL
最初に見たときは、
「ENVって何?」
「なぜ普通の変数ではなく、わざわざ環境変数を使うの?」
と疑問に思いました。
この記事では、環境変数とは何なのかと、実務ではどのように使われているのかを初心者向けにまとめます。
1. 環境変数とは?
一言でまとめると
環境変数とは、アプリの外側からプログラムに設定値を渡す仕組みです。
例えば、Webアプリを動かすためには次のような情報が必要になります。
- データベースの接続先
- データベースのパスワード
- APIキー
- サーバーのポート番号
- バックエンドAPIのURL
- 開発環境なのか本番環境なのか
これらをすべてプログラムのコードに直接書くのではなく、コードとは別の場所で管理して、必要なときにプログラムから読み込むために環境変数を使用します。
イメージとしては次のようになります。
┌─────────────────────┐
│ 環境変数 │
│ │
│ DB_HOST=localhost │
│ DB_USER=root │
│ PORT=3000 │
└──────────┬──────────┘
│
│ 読み込む
▼
┌─────────────────────┐
│ Webアプリ │
│ │
│ Rails / Node.js │
│ React など │
└─────────────────────┘
なぜ環境変数が必要なのか?
大きく分けると理由は3つあります。
① 環境によって設定を変更するため
Webアプリでは一般的に、
開発環境(development)
↓
ステージング環境(staging)
↓
本番環境(production)
のように複数の環境があります。
例えば、RailsからMySQLに接続する場合を考えてみます。
開発中は自分のPCにあるMySQLを使用するため、
localhost
に接続します。
しかし、本番では本番サーバーにあるDBへ接続する必要があります。
| 環境 | DBの接続先 |
|---|---|
| 開発環境 | localhost |
| ステージング環境 | ステージング用DB |
| 本番環境 | 本番用DB |
もし接続先をコードに直接書いてしまうと、環境が変わるたびにコードを書き換えなければいけません。
そこで、
ENV["DB_HOST"]
のようにしておけば、
プログラム
│
└── ENV["DB_HOST"]
│
├─ 開発 → localhost
├─ staging → staging用DB
└─ 本番 → production用DB
というように、同じコードのまま設定だけ変更できます。
② パスワードやAPIキーをコードに直接書かないため
例えば、次のようにAPIキーをコードへ直接書くのは危険です。
api_key = "sk-xxxxxxxxxxxxxxxx"
このコードをGitHubへpushすると、APIキーまでGitの履歴に残ってしまう可能性があります。
そこで、
api_key = ENV["API_KEY"]
とします。
実際のAPIキーはコードとは別に、
API_KEY=xxxxxxxxxxxxxxxx
として管理します。
このように、
「コードとして公開してよいもの」と「秘密にする設定値」を分離できる
ことも環境変数を使う大きな理由です。
③ 設定変更のたびにコードを書き換えないため
例えば、Webサーバーのポート番号を変更するとします。
コードに直接、
port = 3000
と書いてしまうと、3000から8080に変更したい場合にコードを変更する必要があります。
環境変数なら、
port = ENV["PORT"]
としておき、
PORT=3000
を、
PORT=8080
に変更するだけで済みます。
2. 基本的な使い方
ここからは、実際のWeb開発を想定して環境変数を見ていきます。
今回は、
フロントエンド:React + TypeScript
バックエンド:Ruby on Rails
DB:MySQL
という構成を例にします。
使用例① RailsからMySQLへ接続する
RailsからMySQLへ接続するためには、
DBの場所
ユーザー名
パスワード
データベース名
などの情報が必要です。
例えば環境変数として次のように設定します。
DB_HOST=localhost
DB_PORT=3306
DB_NAME=my_app_development
DB_USER=root
DB_PASSWORD=password
Railsではこれらを、
ENV["環境変数名"]
で取得できます。
例えばconfig/database.ymlでは次のように利用できます。
development:
adapter: mysql2
encoding: utf8mb4
host: <%= ENV["DB_HOST"] %>
port: <%= ENV["DB_PORT"] %>
database: <%= ENV["DB_NAME"] %>
username: <%= ENV["DB_USER"] %>
password: <%= ENV["DB_PASSWORD"] %>
ここで、
ENV["DB_HOST"]
は、
「OSに設定されている
DB_HOSTという環境変数の値を取得する」
という意味です。
例えば、
DB_HOST=localhost
なら、
ENV["DB_HOST"]
の結果は、
localhost
になります。
処理の流れは、
環境変数
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=xxxx
│
▼
config/database.yml
│
▼
Rails
│
▼
MySQL
というイメージです。
使用例② ReactからRails APIへアクセスする
ReactとRailsを分離したWebアプリでは、ReactからRailsのAPIへリクエストを送ることがあります。
例えば開発環境のRailsが、
http://localhost:3000
で動いているとします。
.envに、
VITE_API_BASE_URL=http://localhost:3000
と設定します。
Reactでは、
const apiBaseUrl = import.meta.env.VITE_API_BASE_URL;
fetch(`${apiBaseUrl}/users`);
のように利用できます。
すると実際には、
fetch("http://localhost:3000/users");
と同じようなリクエストになります。
本番環境になったら?
本番ではRailsが、
https://api.example.com
で公開されているとします。
本番側の環境変数を、
VITE_API_BASE_URL=https://api.example.com
に変更します。
Reactのコードは、
const apiBaseUrl = import.meta.env.VITE_API_BASE_URL;
fetch(`${apiBaseUrl}/users`);
のままです。
つまり、
【開発環境】
React
│
▼
VITE_API_BASE_URL
│
▼
http://localhost:3000
│
▼
Rails
【本番環境】
React
│
▼
VITE_API_BASE_URL
│
▼
https://api.example.com
│
▼
Rails
となります。
コードを書き換えなくても、環境変数だけでアクセス先を変更できる
というのが重要なポイントです。
使用例③ APIキーを管理する
外部APIを利用する場合も環境変数がよく使われます。
例えば、
API_KEY=xxxxxxxxxxxxxxxx
という環境変数を用意します。
Rails側では、
api_key = ENV["API_KEY"]
として取得できます。
こうすることで、
api_key = "xxxxxxxxxxxxxxxx"
のように秘密情報をコードへ直接書かなくて済みます。
.envファイルとは?
環境変数を勉強していると、
.env
というファイルもよく登場します。
例えば、
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=password
API_KEY=xxxxxxxx
VITE_API_BASE_URL=http://localhost:3000
のような内容です。
ここで注意したいのが、
環境変数と.envは同じものではありません。
.envは、
環境変数として設定したい値を書いておくためによく使われるファイル
です。
イメージとしては、
.env
│
│ 読み込み
▼
環境変数
│
│ 取得
▼
プログラム
となります。
.envをGitHubにpushしない
.envには、
DB_PASSWORD=xxxxxxxx
API_KEY=xxxxxxxx
SECRET_KEY=xxxxxxxx
などの秘密情報が入ることがあります。
そのため通常は.gitignoreに、
.env
と書いてGitの管理対象から外します。
.env
↓
.gitignoreで除外
↓
GitHubにはpushされない
という状態にします。
.env.exampleとは?
会社のリポジトリでは、
.env.example
というファイルを見ることがあります。
例えば、
DB_HOST=
DB_PORT=
DB_NAME=
DB_USER=
DB_PASSWORD=
API_KEY=
のようになっています。
これは、
「このアプリを動かすためには、これらの環境変数を設定してください」
と他の開発者に伝えるためのファイルです。
例えば、新しくプロジェクトに参加したエンジニアは、
cp .env.example .env
などでファイルをコピーして、
DB_HOST=localhost
DB_PORT=3306
DB_NAME=my_app_development
DB_USER=root
DB_PASSWORD=自分の開発環境の値
のように設定します。
そのため、
.env
→ 実際の値
→ Git管理しないことが多い
.env.example
→ 必要な環境変数の一覧
→ Git管理する
という違いがあります。
実務でよく見る環境変数
実際のリポジトリでは、例えば次のような名前を見ることがあります。
| 環境変数 | 用途 |
|---|---|
DATABASE_URL |
DBへの接続情報 |
DB_HOST |
DBサーバーの場所 |
DB_USER |
DBのユーザー名 |
DB_PASSWORD |
DBのパスワード |
PORT |
Webサーバーのポート番号 |
RAILS_ENV |
Railsの実行環境 |
NODE_ENV |
Node.jsの実行環境 |
API_KEY |
外部APIの認証情報 |
SECRET_KEY_BASE |
Railsで利用される秘密情報 |
REDIS_URL |
Redisへの接続先 |
VITE_API_BASE_URL |
Reactから接続するAPIのURL |
プロジェクトによって名前は異なりますが、
DB_
API_
SECRET_
TOKEN
KEY
PASSWORD
URL
HOST
PORT
などが含まれていたら、
「これは環境変数として管理する設定値かもしれない」
と考えると、コードを読みやすくなります。
実務で環境変数を見つけたら確認すること
実務のリポジトリで、
ENV["SOMETHING"]
を見つけたら、まず次の3つを確認すると理解しやすいです。
① 何のための値なのか?
例えば、
ENV["DATABASE_URL"]
なら、
DBへ接続するための情報かな?
と考えます。
② 秘密情報なのか?
例えば、
PASSWORD
TOKEN
API_KEY
SECRET
などが含まれていたら、秘密情報である可能性があります。
その場合、むやみに、
GitHub
Slack
AIチャット
スクリーンショット
などへ貼り付けないよう注意します。
③ どの環境の値なのか?
同じ環境変数でも、
development
staging
production
で値が違うことがあります。
例えば、
DATABASE_URL
だけを見ても、
ローカルDBなのか?
ステージングDBなのか?
本番DBなのか?
を確認することが重要です。
まとめ
環境変数を一言でまとめると、
アプリの外側からプログラムへ設定値を渡すための仕組み
です。
Web開発では主に、
- DBの接続情報
- APIキー
- パスワード
- APIのURL
- ポート番号
- 開発・本番などの環境設定
などに使用されます。
特に重要なのは、
コード
と
環境ごとの設定・秘密情報
を分離できることです。
最初は、
ENV["DATABASE_URL"]
のようなコードを見ると難しく感じますが、
「
DATABASE_URLという名前の設定値を外から取得している」
と考えるとかなり読みやすくなります。
実務で環境変数を見つけたときは、
「何の値なのか」「秘密情報なのか」「どの環境向けなのか」
の3つを確認していきたいと思います。