Open5

Goアプリの設定に.envファイルを使う提案

NoboNoboNoboNobo

direnvのコマンドに「dotenv」というのがあります。
direnvのインストールは各自ググってもらうとして、

.envrc
dotenv local.env

dotenvの引数を省略すると「.env」ファイルを読み込みます。

local.env
PORT=/dev/ttyS0
LOG_DIR="/opt/log"

以上のファイルをプロジェクトフォルダに置いておき、
「direnv allow」することでexportedな環境変数がセットされます。

NoboNoboNoboNobo

Goで環境変数をもとにしたConfigを構築する。

import "github.com/caarlos0/env/v6"

type Config struct {
    Port string `env:"PORT, required"`
    LogDir string `env:"LOG_DIR" envDefault:"/opt/log"`
}

func main() {
    cfg := Config{}
    if err := env.Parse(&cfg); err != nil {
        log.Fatal(err)
    }
    // cfgを参照するコード
}
  • 必須なフィールドには「,required」を付け足しておくとその環境変数がない場合はエラーになります。
  • デフォルト値を指定するときはフィールドタグに「envDefault:"..."」を書きます。
NoboNoboNoboNobo

実環境でどうするか?

一般シェル環境では以下のコマンドで環境変数をセットできる。

set -a; source production.env; set +a

docker runするときには以下のオプションで指定できます。

docker run --env-file=production.env ...

docker-composeでは以下のように指定できる。

docker-compose.yml
server:
  env_file:
    - production.env

systemd用のUnitファイルにも「EnvironmentFile=」で指定できます

server.service
[Unit]
Requires=network.service

[Service]
EnvironmentFile=/opt/server/production.env
...

もちろん、それぞれの方法は複数の「*.env」ファイルを読むこともできる。

NoboNoboNoboNobo

この方法の特徴は

  • docker、direnv、systemdで標準でサポートしているという点に加え、shellコマンドでも利用可能という汎用性
  • サーバーアプリケーションのオプションの取り扱いが環境変数を見るだけというシンプルな実装で済む
  • 一般のCLIほど引数の検証を行わないので変数名の記述には注意が必要です
NoboNoboNoboNobo

以下のコードでenvファイルを環境変数に読み込める。

import "github.com/joho/godotenv"

func init() {
	if err := godotenv.Load(".env"); err != nil {
		log.Fatal(err)
	}
}