プロジェクトに環境変数を設定する - VIPER
数ヶ月前、Golang で環境変数を設定する方法についての記事を書いた。環境変数をいかにエレガントに設定するかは非常に重要なことであり、そのため簡単な関数を自作して対応した。
当時の考えはシンプルで、対応する config ファイルがあれば、その中の key/value を os.Setenv で設定する。その後はアプリ全体で、直接 os.Getenv を使って値を取得できるようにするというものだった。
だが、いざ本番環境にデプロイするとなると、いくつかの問題に直面することになる:
- 設定ファイルが yaml とは限らず、他のフォーマットの場合もある
- 外部サービス(Consul、etcd など)から環境変数を注入したい場合があるが、現状の実装では
os.Getenvを前提としている - 異なるパスから設定ファイルを読み込めるようにしたい
- コマンドライン引数から変数を設定できるようにしたい
- さらに多くの予期せぬ問題
小規模なプロジェクトであればこれで僕の課題は解決できたが、より柔軟な設定方法が必要になると、これだけでは不十分だ。
そして上記の問題に対して、Golang にはすでに Viper という成熟したソリューションが存在する。
VIPER
VIPER は非常に強力な環境設定パッケージだ。以下のような機能をサポートしている:
- デフォルト値の設定
- 様々なフォーマットの設定ファイルのサポート(
json、toml、yaml) - 設定ファイルの変更監視(サーバーを再起動する必要がなくなる!)
- リモートサーバーからの変数取得(例:
consulやetcd) - コマンドラインの
flagによる変数取得 readerからの変数取得(異なるソースから設定を注入できることを意味する)
基本的な使い方
まずは go get や mod を使って VIPER をダウンロードする。
go get github.com/spf13/viper
func main() {
viper.SetDefault("AWS_ACCESS_TOKEN", "AWS123456789") // 設定預設值
viper.SetConfigName("config") // 指定 config 的檔名
viper.AddConfigPath("./config")
viper.ReadInConfig()
viper.AutomaticEnv()
}
SetDefault(key, value):デフォルト値を設定するSetConfigName(name):config のファイル名を設定する。例えば設定ファイルがconfig.ymlの場合はconfigと指定する。なぜ拡張子を指定しなくていいのかというと、Viper が自動的に処理してくれるからだ。AddConfigPath:複数のフォルダ(探索パス)を設定できるReadInConfig:これを呼び出すのを忘れないこと。実際に設定を読み込む処理だAutomaticEnv:ENVの変数を Viper 内に自動で同期する
Viper は設定を容易にするための関数を他にも多数提供している。
変数の取得
変数を設定した後は、viper.Get を使って読み取ることができる。Get が返すのは interface{} だが、Viper は viper.GetString、viper.GetDuration、viper.GetStringMap など、数多くの型変換メソッドも提供している。
func main() {
fmt.Println(viper.GetString("AWS_ACCESS_TOKEN"))
fmt.Println(viper.GetUint32("YOUR_INT"))
fmt.Println(viper.GetTime("YOUR_TIME"))
}
まとめ
環境設定は難しいといえば難しく、簡単といえば簡単だが、考慮すべきことは想像以上に多い。そして VIPER は、よくあるユースケースの多くを肩代わりして処理してくれる。
また、特に注意すべき点として、access token や secret key などを設定する際は、コミット時に誤って GitHub にプッシュして取り返しのつかない事態にならないよう、必ず .gitignore に追加しておくことを忘れないでほしい。
関連記事
- 測定が目標になるとき:窓税からPull Request数まで かつて僕は小さなツールを自作し、四半期で自分がどれだけPRに貢献したか、レビューコメントをどれだけ残したか、チケットをどれだけ消化したかを集計して、上司にアウトプットを証明しようとしたことがある。上司は淡々と、評価はアウトプットだけで見るものではないと言った。数年後、僕はようやく理解した――測定が目標になるとき、それはもはや良い測定ではなくなるのだ。英国の窓税、ハノイのネズミ駆除の報奨金から、現代のPR数による開発者評価に至るまで、そのメカニズムはまったく同じだ。
- Cloudflare Images を画像ストレージ・変換ソリューションとして使う ウェブページに画像を1枚置くのはフロントエンドにとって最も簡単なことだが、リサイズや各種フォーマットの生成、さらにはトラフィックの負荷に耐えることまで完璧にやろうとすると、実際には一つの包括的なソリューションが必要になる。僕はその後、すべて Cloudflare Images に任せるようになり、オリジナル画像1枚だけを渡すようにしている。
- もう AWS Access Key を使うのはやめよう Access Key は AWS において見落とされがちなセキュリティリスクだ。OIDC と IAM Role を組み合わせることで、GitHub Actions にシークレットを一切保持させることなく、安全に AWS リソースを操作できるようにする。
- データベース主キー:AUTO_INCREMENT、UUID、そしてUUIDv7 バックエンド開発で度々直面する主キーの決定。auto incrementを使うべきか、それともUUIDか?衝突への懸念は?UUIDv7とcreated_at + インデックスの性能差はどれほどか?実際に2,000万件のデータで検証したベンチマークと設計上の意思決定を解説する。