WSLで「direnv」を活用してプロジェクト単位で環境変数を管理しよう

はじめに
近年、アプリケーションの実行環境として最も選択されているのはクラウドです。運用の簡素化やコスト効率など様々なメリットがありますが、クラウドを選択する理由の1つとして「スケーラビリティ」があります。スケーラビリティとは、環境やリソースを拡張できる能力を指します。柔軟に環境やリソースを追加できるのは、クラウド利用の最大のメリットと言えるでしょう。
クラウド利用を念頭に置いた設計思想を「クラウドネイティブ」と呼びます。クラウドネイティブなアプリケーションには、以下のような特徴があります:
- Twelve-Factor App準拠
- コンテナ化とオーケストレーション
- マイクロサービスアーキテクチャ
- クラウドの特徴を活かした設計
この中の1つ、Twelve-Factor Appには「設定を環境変数に格納する」と明示されています。
アプリケーションの設定は複数の環境(開発、ステージング、本番)で異なります。例えば、DBへの接続情報やホスト名など、これらの機密情報をアプリケーションと同じリポジトリで管理するわけにはいきません。つまり、環境ごとに設定ファイルを用意するより、環境変数から設定できる方がよりセキュアであると言えるでしょう。
このようなアプリケーションを開発するには、開発環境でも環境変数の管理が必要となります。特に、複数のプロジェクトを同時に扱う場合や複数の環境で作業する場合は、環境変数の切り替えが煩雑になりがちです。
このような課題を解決するツールとして「direnv
」があります。
direnvとは
direnvは、ディレクトリごとに環境変数を自動的に設定・切り替えができるユーティリティです。これにより、プロジェクトや環境ごとの環境設定を簡単に管理できるようになります。
例えば、以下のようなシーンでdirenvは特に有用です:
- 複数のKubernetesクラスターを管理する場合
- 異なる環境の認証情報を扱う場合
- プロジェクト固有の環境変数を設定する場合
この記事では、このdirenvを活用しながら、よりスムーズな開発体験を実現する方法を紹介します。
なぜdirenvが必要なのか
現代のアプリケーション開発では、環境変数を使用して設定を管理することが一般的です。しかし、以下のような課題があります:
- プロジェクトごとに異なる環境変数が必要
- 環境変数の設定を忘れてしまう
- 環境変数の管理が煩雑
- チームメンバー間での環境変数の共有が難しい
direnvはこれらの課題を解決し、より効率的な開発環境の構築を可能にします。
direnvの特徴
- 自動的な環境変数の設定
- ディレクトリに入ったときに自動的に環境変数を設定
- ディレクトリから出たときに自動的に環境変数を解除
- シンプルな設定ファイル
.envrc
ファイルで環境変数を管理- シンプルな構文で設定可能
- セキュリティ
- 設定ファイルの変更を検知
- 信頼できる設定ファイルのみを実行
- クロスプラットフォーム対応
- Linux、macOS、Windowsで動作
- 様々なシェルに対応
Windowsとの相性はイマイチ、WSLは◎
前述の「クロスプラットフォーム対応」の中でWindowsもその候補に挙げました。たしかにバイナリは配布されていますし、インストールも問題ありません。しかし、私のWindows 11環境では正しく動作しませんでした。動作確認を行うと、設定の不足や不明なエラーでかなりハマります。Windows関連のIssueも沢山上がっているようなので、まだ安定していないのかもしれません。
これはdirenvに限らず、Linux向けツールの多くは、Windowsでうまく動かない、または、動かすのに苦労することが少なくありません。そういう意味でも、Linux向けのツールをそのまま動かせるWSLの存在は、非常に大きいと言えるでしょう。
そのため、この記事ではWSL環境における使用に絞って解説していきます。
セットアップ
ここからは、WSL環境で作業します。
インストール
$ sudo apt install -U -y direnv
フックの設定
$ echo 'eval "$(direnv hook bash)"' >> ~/.bashrc
フックの設定が完了したらターミナルを再起動し、設定を読み込ませましょう。
基本的な使い方
今回は、仮に「project_a」と「project_b」ディレクトリで動作確認を行います。
mkdir ~/project_{a,b}
project_aディレクトリに.envrcファイルを作成
$ echo 'export PROJECT=A' > ~/project_a/.envrc
PROJECT環境変数にA
という値を設定します。
設定ファイルを信頼
$ direnv allow ~/project_a
direnv allow
に続き、信頼する設定ファイルが置かれているディレクトリを指定します。
動作確認
$ cd ~/project_a direnv: loading ~/project_a/.envrc direnv: export +PROJECT $ echo $PROJECT A
project_aディレクトリに入ると.envrcが読み込まれ、PROJECT環境変数にAがセットされます。
$ cd .. direnv: unloading $ echo $PROJECT
project_aディレクトリから出ると環境変数が解放されます。
project_bディレクトリに.envrcファイルを作成
$ echo 'export PROJECT=B' > ~/project_b/.envrc
PROJECT環境変数にB
という値を設定します。
設定ファイルを信頼
$ direnv allow ~/project_b
動作確認
$ cd ~/project_b direnv: loading ~/project_b/.envrc direnv: export +PROJECT $ echo $PROJECT B
project_bディレクトリに入ると.envrcが読み込まれ、PROJECT環境変数にBがセットされます。
$ cd .. direnv: unloading $ echo $PROJECT
project_bディレクトリから出ると環境変数が解放されます。
よく見られる使用事例
「開発環境」と「本番環境」という複数の環境を対象に作業していることを想定してみましょう。以降の作業はproject_cディレクトリ以下で行うので、ディレクトリを作成し、移動しておいてください。
$ mkdir ~/project_c $ cd ~/project_c
開発環境の設定
アプリ開発のため、下記の3つの環境変数が必要だとしましょう。
- データベースの接続情報
- デバッグモードの有無
- APIエンドポイントの設定
project_cディレクトリ内に、以下の内容で.envrcを作成してください。
export DATABASE_URL="postgres://localhost:5432/dev_db" export DEBUG=true export API_ENDPOINT="http://localhost:3000"
.envrcを編集するとdirenvが変更を検知し、`Run `direnv allow` to approve its content`
のようなメッセージが出力されます。このメッセージが出力されたらdirenv allow ~/project_c
を実行しておいてください。
これで、開発環境における環境変数が自動的にセットされるようになりました。ここまでは、すでに解説した通りです。
環境ごとの設定を切り替え
前述の設定だけだと、開発環境向けの環境変数しか設定できていません。本番環境と簡単に切り替えられると便利です。
まず.envというファイルを以下の内容で作成してください。.envは「dotenv」というライブラリがデフォルトで読み込む設定ファイルです。ここに書かれた値が環境変数として利用されます。様々なランタイムで実装され、.envファイルをデフォルトで読み込むプログラムも増えてきています。ここでは開発環境(DEV)と本番環境(PROD)それぞれのAPIキーを環境変数にセットしています。また、ENV環境変数に「prod」を指定しています。
DEV_API_KEY=0123456789 PROD_API_KEY=9876543210 ENV=prod
.envはあくまで環境変数のセットを管理するだけなので、環境そのものは切り替えできません。そこで、direnvを挟むことで環境の切り替えを実現できます。先ほど作成した.envrcを、以下の内容で書き換えてください。
# .envrcと同じ階層に.envファイルがあれば読み込む if [ -f "$PWD/.env" ]; then source "$PWD/.env" fi # ENVにprodが設定されていれば本番用の値を環境変数にセット if [ "$ENV" = "prod" ]; then export DATABASE_URL="postgres://prod-db:5432/prod_db" export DEBUG=false export API_ENDPOINT="http://prod-api:3000" # .envから読み込んだ本番用のAPI_KEYをセット export API_KEY=$PROD_API_KEY # ENVがprod以外の場合は開発用の値を環境変数にセット else export DATABASE_URL="postgres://localhost:5432/dev_db" export DEBUG=true export API_ENDPOINT="http://localhost:3000" # .envから読み込んだ開発用のAPI_KEYをセット export API_KEY=$DEV_API_KEY fi
ここまでの説明でお気づきの方もいるかもしれませんが、.envrcにはシェルスクリプトが記述されています。実際のところ.envrcはただのシェルスクリプトなのです。このディレクトリに入るとスクリプトが実行され、exportした環境変数がこのディレクトリ下で有効になります。言い換えると、direnvを使用すればディレクトリへの移動をトリガーとして、任意の処理を実行できるというわけです。
想定される運用
プロジェクト内で共通の環境変数を使用する場合は、.envrcをプロジェクトのリポジトリに含めると良いでしょう。ただし、リポジトリで管理するのであれば機密情報を書くべきではありません。その場合は前述の「環境ごとの設定を切り替え」の項でも行っている通り.envに機密情報を記述し、それを読み込むようにすれば良いでしょう。その際は.envをリポジトリに含めてはいけません。
おわりに
direnvは環境変数の管理を効率化し、開発プロセスをスムーズにする強力なツールです。適切に使用することで環境設定の管理が容易になり、チーム開発の効率も向上します。プロジェクトの規模や複雑さに関わらず、導入を検討する価値があります。
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- 「Pulumi Stack」とは ー Pulumiによるマルチステージ環境の構築方法
- kustomizeで復数環境のマニフェストファイルを簡単整理
- PulumiでAWSリソースをデプロイしよう
- バージョン管理を柔軟に! プロジェクト単位で「asdf」を使いこなす
- WSLとWindowsの設定ファイルを「chezmoi」を使って安全に管理しよう
- SecretもPulumiで使いこなしたい! PulumiのSecurityを試してみよう
- kustomizeやSecretを利用してJavaアプリケーションをデプロイする
- 「mmdebstrap」でUbuntuをカスタマイズして、オリジナルのWSLディストリビューションを作ろう
- 「Bash」をカスタマイズして、Linuxをより便利に使いこなそう
- Hyperledger Fabricに関連する2つのプロジェクトとHyperledger Fabricに関するリソース