Rustで環境変数を扱う

AWS Lambda、あるいはAmazon ECSなどのコンテナサービスでは、アプリケーションの各種パラメーターを環境変数を使って管理するのが定石かと思います(これらのサービスに限った話ではありませんが)。

RustでAWS Lambdaファンクションを実装するにあたり、Rustで環境変数を扱う方法を調査したのでその結果を記録しておきます。

目次

検証環境

  • macOS:Mojave(v10.14.3)
  • Rust:1.32.0

スタンダードライブラリ(std::env)

std::env::varで環境変数の値を取得できます。少数の環境変数を扱う場合はこれで十分かもしれません。

std::env::varの戻り値はStringなので、必要に応じて数値型等に変換します。

ちなみに、スタンダードライブラリにはstd::env!というマクロもあります。このマクロはコンパイル時に環境変数の値を取得するもので、アプリケーションの起動時に環境変数の値を取得して、、という使い方は出来ません。

環境変数を構造体で扱う

環境変数にセットしたアプリケーションの設定一式を以下のような構造体で扱えると便利ですし、そうするのが一般的かと思います。

struct Config {
  host: String,
  port: Option<u16>,
  numbers: Vec<u64>,
}

std::env::varで1つ1つ環境変数の値を取得するのは面倒なので、、環境変数を自動的に構造体にデシリアライズしてくれるライブラリを2つ試してみました。

envy

envySerdeを使って実装されています。構造体を定義しenvy::from_env::<T>()を呼ぶだけで、自動的に環境変数を構造体にデシリアライズしてくれます。

簡単ですね。なお、カンマ区切りの値はベクターにデシリアライズされます。

プレフィックス指定での値の取得

デシリアライズする環境変数をプレフィックスで指定することができます。例えば以下のような環境変数があった場合、envy::prefixed("APP_").from_env::<T>()APP_始まりの環境変数のみがデシリアライズされます。

APP_HOST=myserver
PORT=8080
APP_NUMBERS=1,2,3

デフォルト値の設定

構造体のフィールドに#[serde(default = "path")]アトリビュートを適用することで、パラーメータのデフォルト値を設定することができます。

今回は試していませんが、defaultの他にもSerdeのアトリビュートが利用できるようです。

envconfig

envconfig-rsはenvyと類似のライブラリです。こちらはSerdeには依存していません。構造体の個々のフィールドに対して#[envconfig]アトリビュートでデシリアライズ対象の環境変数を指定します。

envy同様、使い方はシンプルです。「カンマ区切りの値はベクターにデシリアライズ」は出来ませんでした。

まとめ

envyが使いやすい印象を受けたので、しばらく使ってみたいと思います。envyと同じ作者の方がAWS Systems Manager パラメータストアを構造体にデシリアライズするライブラリenvy-storeも公開しているので、こちらも試してみたいと思います。