概要
Rustで環境変数を扱う場合、一般的なライブラリはstd::envです。
しかし、
- 環境(開発/検証/本番)によって使い分けたい
- 環境変数が沢山あって手動で設定するのが大変
といったことがあります。
dotenvを使うと、.envというファイルで環境変数を管理することができます。
(dotenv自体はRuby発のOSSでNode.jsやRustに移植されています)
使い方を紹介していきます。
dotenv
依存関係
現在(2021年3月22日)の最新バージョンは0.15.0です。
Cargo.tomlは以下。
[package]
...略
[dependencies]
dotenv = "0.15.0"
使い方
基本的な使い方
基本的な使い方はdotenv().ok()で.envファイルを読み込んでstd::envから環境変数を使うパターンです。
以下はDieselでデータベースの接続情報を取得している例です。
DATABASE_URL=postgres://root:root@localhost/rust-dev
use diesel::prelude::*;
use diesel::pg::PgConnection;
use dotenv::dotenv;
use std::env;
pub fn establish_connection() -> PgConnection {
dotenv().ok();
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
PgConnection::establish(&database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", database_url))
}
その他の使い方
.envファイルを読み込んで環境変数を使う方法です。
キーを指定して取得
dotenv::varで環境変数のキーを指定してバリューを取得できます。
use dotenv;
let key = "FOO";
let value = dotenv::var(key).unwrap();
環境変数を全て取得
dotenv::varsで環境変数(キー・バリュー)を全て取得できます。
use dotenv;
use std::io;
let result: Vec<(String, String)> = dotenv::vars().collect();
iteratorで取得
dotenv::dotenv_iterでイテレータとして取得できます。
use dotenv;
for item in dotenv::dotenv_iter().unwrap() {
let (key, val) = item.unwrap();
println!("{}={}", key, val);
}
ファイルを指定して読み込んで使う方法
.env以外のファイルを指定して読み込んで環境変数を使う方法です。
カレントディレクトリのファイルを読み込む
dotenv::from_filenameで読み込めます。
use dotenv;
dotenv::from_filename("custom.env").ok();
このあとはdotenv::dotenv()と同じようにstd::envで値を読み込めます。
dotenv::dotenv_iterと同じようにイテレータで取得することもできます。
use dotenv;
let iter = dotenv::from_filename_iter(".env").unwrap();
for item in iter {
let (key, val) = item.unwrap();
println!("{}={}", key, val);
}
パス指定してファイルを読み込む
dotenv::from_pathで読み込めます。
use dotenv;
use std::env;
use std::path::{Path};
let my_path = env::home_dir().and_then(|a| Some(a.join("/.env"))).unwrap();
dotenv::from_path(my_path.as_path());
from_filenameと同じようにイテレータで取得することもできます。
use dotenv;
use std::env;
use std::path::{Path};
let my_path = env::home_dir().and_then(|a| Some(a.join("/.env"))).unwrap();
let iter = dotenv::from_path_iter(my_path.as_path()).unwrap();
for item in iter {
let (key, val) = item.unwrap();
println!("{}={}", key, val);
}
実用的な使い方
.envファイルに一般的な設定(共通の設定)を行い、各環境固有の設定を各.envファイルに記載するのがよくある使い方のようです。
.envファイルは必ず読み込んで、各環境用の.envファイルを追加で読み込む形です。
dotenvで調べると、RubyやNode.jsでの使い方は出てくると思うので、参考にすると良いと思います。
まとめ
ローカル/共有・開発/テスト/本番など、環境によって違う設定をファイル1つで変えることができるので便利ですね。
おまけにも書きますが、使い方のベストプラクティスは幾つかあるようなので各環境にあわせて考えることが大事かと。
おまけ
dotenvで調べるとRubyとNode.jsで思想が違っていて面白かったです。
Rubyでは、
- 各環境ごとの.envファイルは作成してよい
- 共有の環境の.envファイルであればcommitしてよい
Node.jsでは逆に
- 各環境ごとの.envファイルは作成は非推奨
- .envファイルのcommitは非推奨
です。
RustのdotenvはRubyを参考にしているようなので、Rubyの思想にあわせるのが自然かなと思いました。