🍏webアプリ開発における環境変数まわりのベストプラクティス2022/03/09に公開2024/09/115件環境変数ベストプラクティスtechDiscussionError4012022/03/11に更新 環境はその3つだけではなく、開発環境のなかでも設定値のバリエーションが生まれたりします。いっそのこと開発環境・テスト環境・本番環境と区別せずに、設定の値だけ環境変数を増やすほうがこのバリエーションに対応できます。 うーん、新しい環境が必要なら、development.yaml, test.yaml, production.yamlがあるところに、staging.yamlを追加します、という方式(大抵のFW/ライブラリ/ミドルウェアが採用している方式)がいい気がします。 どの環境でも同じ環境変数を参照する仕組みにする場合、結局の所、staging.envとかstaging_setenv.shが必要になりませんか? ハトすけ2022/03/11コメントありがとうございます! うーん、新しい環境が必要なら、development.yaml, test.yaml, production.yamlがあるところに、staging.yamlを追加します、という方式(大抵のFW/ライブラリ/ミドルウェアが採用している方式)がいい気がします。 はい、そうですね、僕もそう思います。ちょっとわかりにくい表現をしてしまいました。ここで伝えたかったことは、アプリケーションコード自体に自分がいまどの環境にいるのかを意識させないということでした。これは言い換えればコードの中に環境識別情報を変数(今回で言うところのNODE_ENV)でif分岐させないという意味です。 例えば以下のようなコードですね。こうなると環境が増えるたびにコード内にNODE_ENVをもとにした分岐が増えていきます。 アプリケーションコード if(開発環境){ const logger = new Logger({ level: 'debug' }); } else if (ステージング環境){ const logger = new Logger({ level: 'debug' }); } else if (本番環境){ const logger = new Logger({ level: 'debug' }); } それよりも、その環境による差分を、.env.developmentや.env.productionやenv.stagingに入れてしまって .env.development LOG_LEVEL=debug .env.production LOG_LEVEL=error .env.stg LOG_LEVEL=info アプリケーションコードは素直にその環境変数を受け入れるようにしようという意味でした。 アプリケーションコード const logger = new Logger({ level: process.env.LOG_LEVEL }); 記事の方をもう少し表現変えたいと思います^^ 返信を追加ハトすけ2022/03/11 内容変更 変更箇所1 表現の変更 アプリの環境(例えばNODE_ENV)によって設定を分岐しない -> アプリケーションコードに自分が今いる環境(開発|ステージング|本番)を意識させない 削除 よくDBとかで開発環境・テスト環境・本番環境ごとに設定を分岐させることがあります。The Twelve-Factor Appでも言及されているように、環境はその3つだけではなく、開発環境のなかでも設定値のバリエーションが生まれたりします。いっそのこと開発環境・テスト環境・本番環境と区別せずに、設定の値だけ環境変数を増やすほうがこのバリエーションに対応できます。ただし、環境を扱う環境変数(NODE_ENV)で分岐させたほうが素直な場合も極稀にあります(フレームワークがNODE_ENV環境によって挙動を変えるときとか)。 追記 これはつまり、コード内で環境識別変数(今回で言うところのNODE_ENV)によってif分岐を作らないという意味です。各環境にどのような設定が入るかはアプリケーションコード外にその種類分作成しましょう! 変更箇所2 表現の変更 アプリ自体を.envに依存させない -> アプリに自分から環境変数を取りに行かせない。 削除 .envを読み込む設定の場合、開発環境ではいいのですが、本番環境だと.envを作成管理しなければいけません。できれば、本番環境はその環境の環境変数をそのまま使うほうが扱いやすいです。各本番環境ごとに、それぞれの環境変数を設定するだけで済みます。 追記 なぜこのようなことをするかというと、アプリ自体に環境変数を能動的に取得してほしくないからです。これは「アプリケーションコードに自分が今いる環境(開発|ステージング|本番)を意識させない」と似ていますが、アプリ側にどの.envに依存するのか、依存しないのかの判断をさせないための防御手段です。アプリ側には素直に渡された環境変数のみに依存してほしいのです。 アプリ自体はピュアに保っておき、どの.envに依存するのか、依存しないのかのバリエーションは外部が注入してあげます。 アプリ自体をピュアに保っていると、本番環境の環境変数を設定しやすいというメリットもあります。 返信を追加イカフライ2024/03/04に更新とても参考になるいい記事でした。ありがとうございます。 一点だけ誤字を見つけたので共有します。 誤 基本.envは気密性の高い項目にはダミーデータしか置かないほうがいいですね。 正 基本.envは機密性の高い項目にはダミーデータしか置かないほうがいいですね。 返信を追加Shota Tamura2024/09/12まさにAPP_ENVやらNODE_ENVを量産して地獄をみた経験があるので首がもげました。「あえて知らせないほうがうまくいく」ことがあるのは人間界でもコンピューター界でも一緒ですねぇ... 返信を追加
Error4012022/03/11に更新 環境はその3つだけではなく、開発環境のなかでも設定値のバリエーションが生まれたりします。いっそのこと開発環境・テスト環境・本番環境と区別せずに、設定の値だけ環境変数を増やすほうがこのバリエーションに対応できます。 うーん、新しい環境が必要なら、development.yaml, test.yaml, production.yamlがあるところに、staging.yamlを追加します、という方式(大抵のFW/ライブラリ/ミドルウェアが採用している方式)がいい気がします。 どの環境でも同じ環境変数を参照する仕組みにする場合、結局の所、staging.envとかstaging_setenv.shが必要になりませんか? ハトすけ2022/03/11コメントありがとうございます! うーん、新しい環境が必要なら、development.yaml, test.yaml, production.yamlがあるところに、staging.yamlを追加します、という方式(大抵のFW/ライブラリ/ミドルウェアが採用している方式)がいい気がします。 はい、そうですね、僕もそう思います。ちょっとわかりにくい表現をしてしまいました。ここで伝えたかったことは、アプリケーションコード自体に自分がいまどの環境にいるのかを意識させないということでした。これは言い換えればコードの中に環境識別情報を変数(今回で言うところのNODE_ENV)でif分岐させないという意味です。 例えば以下のようなコードですね。こうなると環境が増えるたびにコード内にNODE_ENVをもとにした分岐が増えていきます。 アプリケーションコード if(開発環境){ const logger = new Logger({ level: 'debug' }); } else if (ステージング環境){ const logger = new Logger({ level: 'debug' }); } else if (本番環境){ const logger = new Logger({ level: 'debug' }); } それよりも、その環境による差分を、.env.developmentや.env.productionやenv.stagingに入れてしまって .env.development LOG_LEVEL=debug .env.production LOG_LEVEL=error .env.stg LOG_LEVEL=info アプリケーションコードは素直にその環境変数を受け入れるようにしようという意味でした。 アプリケーションコード const logger = new Logger({ level: process.env.LOG_LEVEL }); 記事の方をもう少し表現変えたいと思います^^ 返信を追加
ハトすけ2022/03/11コメントありがとうございます! うーん、新しい環境が必要なら、development.yaml, test.yaml, production.yamlがあるところに、staging.yamlを追加します、という方式(大抵のFW/ライブラリ/ミドルウェアが採用している方式)がいい気がします。 はい、そうですね、僕もそう思います。ちょっとわかりにくい表現をしてしまいました。ここで伝えたかったことは、アプリケーションコード自体に自分がいまどの環境にいるのかを意識させないということでした。これは言い換えればコードの中に環境識別情報を変数(今回で言うところのNODE_ENV)でif分岐させないという意味です。 例えば以下のようなコードですね。こうなると環境が増えるたびにコード内にNODE_ENVをもとにした分岐が増えていきます。 アプリケーションコード if(開発環境){ const logger = new Logger({ level: 'debug' }); } else if (ステージング環境){ const logger = new Logger({ level: 'debug' }); } else if (本番環境){ const logger = new Logger({ level: 'debug' }); } それよりも、その環境による差分を、.env.developmentや.env.productionやenv.stagingに入れてしまって .env.development LOG_LEVEL=debug .env.production LOG_LEVEL=error .env.stg LOG_LEVEL=info アプリケーションコードは素直にその環境変数を受け入れるようにしようという意味でした。 アプリケーションコード const logger = new Logger({ level: process.env.LOG_LEVEL }); 記事の方をもう少し表現変えたいと思います^^
ハトすけ2022/03/11 内容変更 変更箇所1 表現の変更 アプリの環境(例えばNODE_ENV)によって設定を分岐しない -> アプリケーションコードに自分が今いる環境(開発|ステージング|本番)を意識させない 削除 よくDBとかで開発環境・テスト環境・本番環境ごとに設定を分岐させることがあります。The Twelve-Factor Appでも言及されているように、環境はその3つだけではなく、開発環境のなかでも設定値のバリエーションが生まれたりします。いっそのこと開発環境・テスト環境・本番環境と区別せずに、設定の値だけ環境変数を増やすほうがこのバリエーションに対応できます。ただし、環境を扱う環境変数(NODE_ENV)で分岐させたほうが素直な場合も極稀にあります(フレームワークがNODE_ENV環境によって挙動を変えるときとか)。 追記 これはつまり、コード内で環境識別変数(今回で言うところのNODE_ENV)によってif分岐を作らないという意味です。各環境にどのような設定が入るかはアプリケーションコード外にその種類分作成しましょう! 変更箇所2 表現の変更 アプリ自体を.envに依存させない -> アプリに自分から環境変数を取りに行かせない。 削除 .envを読み込む設定の場合、開発環境ではいいのですが、本番環境だと.envを作成管理しなければいけません。できれば、本番環境はその環境の環境変数をそのまま使うほうが扱いやすいです。各本番環境ごとに、それぞれの環境変数を設定するだけで済みます。 追記 なぜこのようなことをするかというと、アプリ自体に環境変数を能動的に取得してほしくないからです。これは「アプリケーションコードに自分が今いる環境(開発|ステージング|本番)を意識させない」と似ていますが、アプリ側にどの.envに依存するのか、依存しないのかの判断をさせないための防御手段です。アプリ側には素直に渡された環境変数のみに依存してほしいのです。 アプリ自体はピュアに保っておき、どの.envに依存するのか、依存しないのかのバリエーションは外部が注入してあげます。 アプリ自体をピュアに保っていると、本番環境の環境変数を設定しやすいというメリットもあります。 返信を追加
イカフライ2024/03/04に更新とても参考になるいい記事でした。ありがとうございます。 一点だけ誤字を見つけたので共有します。 誤 基本.envは気密性の高い項目にはダミーデータしか置かないほうがいいですね。 正 基本.envは機密性の高い項目にはダミーデータしか置かないほうがいいですね。 返信を追加
Shota Tamura2024/09/12まさにAPP_ENVやらNODE_ENVを量産して地獄をみた経験があるので首がもげました。「あえて知らせないほうがうまくいく」ことがあるのは人間界でもコンピューター界でも一緒ですねぇ... 返信を追加
Discussion
うーん、新しい環境が必要なら、development.yaml, test.yaml, production.yamlがあるところに、staging.yamlを追加します、という方式(大抵のFW/ライブラリ/ミドルウェアが採用している方式)がいい気がします。
どの環境でも同じ環境変数を参照する仕組みにする場合、結局の所、staging.envとかstaging_setenv.shが必要になりませんか?
コメントありがとうございます!
はい、そうですね、僕もそう思います。ちょっとわかりにくい表現をしてしまいました。ここで伝えたかったことは、アプリケーションコード自体に自分がいまどの環境にいるのかを意識させないということでした。これは言い換えればコードの中に環境識別情報を変数(今回で言うところのNODE_ENV)でif分岐させないという意味です。
例えば以下のようなコードですね。こうなると環境が増えるたびにコード内にNODE_ENVをもとにした分岐が増えていきます。
それよりも、その環境による差分を、
.env.developmentや.env.productionやenv.stagingに入れてしまってアプリケーションコードは素直にその環境変数を受け入れるようにしようという意味でした。
記事の方をもう少し表現変えたいと思います^^
内容変更
変更箇所1
表現の変更
アプリの環境(例えばNODE_ENV)によって設定を分岐しない
->
アプリケーションコードに自分が今いる環境(開発|ステージング|本番)を意識させない
削除
よくDBとかで開発環境・テスト環境・本番環境ごとに設定を分岐させることがあります。The Twelve-Factor Appでも言及されているように、環境はその3つだけではなく、開発環境のなかでも設定値のバリエーションが生まれたりします。いっそのこと開発環境・テスト環境・本番環境と区別せずに、設定の値だけ環境変数を増やすほうがこのバリエーションに対応できます。ただし、環境を扱う環境変数(NODE_ENV)で分岐させたほうが素直な場合も極稀にあります(フレームワークが
NODE_ENV環境によって挙動を変えるときとか)。追記
これはつまり、コード内で環境識別変数(今回で言うところのNODE_ENV)によってif分岐を作らないという意味です。各環境にどのような設定が入るかはアプリケーションコード外にその種類分作成しましょう!
変更箇所2
表現の変更
アプリ自体を
.envに依存させない->
アプリに自分から環境変数を取りに行かせない。
削除
.envを読み込む設定の場合、開発環境ではいいのですが、本番環境だと.envを作成管理しなければいけません。できれば、本番環境はその環境の環境変数をそのまま使うほうが扱いやすいです。各本番環境ごとに、それぞれの環境変数を設定するだけで済みます。追記
なぜこのようなことをするかというと、アプリ自体に環境変数を能動的に取得してほしくないからです。これは「アプリケーションコードに自分が今いる環境(開発|ステージング|本番)を意識させない」と似ていますが、アプリ側にどの
.envに依存するのか、依存しないのかの判断をさせないための防御手段です。アプリ側には素直に渡された環境変数のみに依存してほしいのです。アプリ自体はピュアに保っておき、どの
.envに依存するのか、依存しないのかのバリエーションは外部が注入してあげます。アプリ自体をピュアに保っていると、本番環境の環境変数を設定しやすいというメリットもあります。
とても参考になるいい記事でした。ありがとうございます。
一点だけ誤字を見つけたので共有します。
誤
基本.envは
気密性の高い項目にはダミーデータしか置かないほうがいいですね。正
基本.envは
機密性の高い項目にはダミーデータしか置かないほうがいいですね。まさに
APP_ENVやらNODE_ENVを量産して地獄をみた経験があるので首がもげました。「あえて知らせないほうがうまくいく」ことがあるのは人間界でもコンピューター界でも一緒ですねぇ...