はじめまして、よりそうでSREを担当しているうちだです。
みなさんはバックエンドサービスで環境変数は使ってますか?
The Twelve-Factor Appにも環境変数を使うんだぜ?といったことが書かれています。
そこで、環境変数を使うことで何がいいのかを書いていきたいと思います。
ちなみに、バックエンドサービスはコンテナで実行することを前提としています。
そもそも環境変数って何?
環境変数というのはOSが提供する変数の一つで、設定した値はプロセスの子、孫と継承されていきます。
主要なOSではほぼサポートされている機構になります。
設定の仕方は使用しているシェルによって異なります。
- bash/zhsの場合
export foo=var
- PowerShellの場合
$Env:foo = "var"
また、コンテナイメージの場合は実行時にパラメータで環境変数を設定することが可能です。
- Dockerの場合
docker run --env='foo=var' --env='hoge=fuga' debian:latest env
環境変数を使うと何がいいの?
では、環境変数を使うことで何がいいんでしょうか?
先程、`コンテナイメージの場合は実行時にパラメータで環境変数を設定することが可能と説明しました。
つまり、コンテナイメージの中に環境依存値を内包しなくて済むんです。
つまりはどういう事?
例えばDBの接続情報。
本番環境と開発環境では接続するインスタンスはもとより、ユーザー名やパスワードすら違うことはよくあることだと思います。
接続情報を内包してしまうと、本番環境しか使えないコンテナイメージになってしまいますよね?
パスワードはものの例えです。
パスワードのように機密性の高い設定値は環境変数で設定せずにSecretなどを利用しましょう。
でも開発環境で実行したいものは本番で実行したいモノ(バイナリ)とはちょっと違ったりするよ?
そうですね。
開発環境で動いているものをそのまま本番環境で動かすというのは環境依存値を除外してもわりとレアなケースだと思います。
でも、ステージング環境と本番環境ではどうですか?
ステージング環境で検証が完了したコンテナイメージをそのまま本番環境で実行したくないですか?
もしステージング環境で検証出来たコンテナイメージを本番環境でも実行出来るなら、バイナリの同一性も担保できる上、本番環境とステージング環境で個別のビルドが不要になりますよね。
また、本番で障害が起きたときに本番で実行しているコンテナイメージをローカルで実行するなんてことも出来ますよ。
本番で実行しているコンテナイメージをローカルで実行する場合はSecretへのアクセスが問題になることもあります。
機密情報についてはSecretにアクセスできなかった場合は環境変数から取得するような実装をしておくことも有用です。
定義ファイルをマウントすればいいんじゃないの?
Dockerなどでローカルでのみ実行する場合はそれでも良いと思います。
しかし、クラウドサービスによっては外部ストレージをマウント出来なかったりします。
少し前までのCloud Runなどはストレージのマウントが出来ませんでした。
今でも一工夫必要です(2023/12/8現在)。
ならコマンドライン引数でいいんじゃない?
コマンドライン引数にした場合、コンテナイメージのENTRYPOINTの指定によってはENTRYPOINT自身を上書きする必要があったり、引数が長すぎてメンテしにくかったり、文字数の上限に達して指定が出来なかったりするのでオススメはしません。
環境変数、ちょっと便利かも
CI/CDにも一工夫必要ですが、環境変数を使うことでビルドの無駄を省いたり、トラブルシューティングがしやすくなるので、ぜひ環境変数を使ってみて下さい。