はじめに
開発環境では .env
ファイルを利用して環境変数を管理することが一般的ですが、本番環境(特に AWS ECS などのクラウド環境)では .env
ファイルがなくても動作するように設計する必要があります。
今回、ECS にデプロイした Go アプリケーションで 「.env
ファイルが読み込めません」 というエラーが発生しました。その原因と対処法について解説します。
起きていたエラー
ECS 上で Go アプリケーションをデプロイした際に、以下のエラーが発生しました。
2025/02/19 02:11:07 .envファイルが読み込めません: open .env: no such file or directory
このエラーは、Go アプリケーションが .env
ファイルを読み込もうとして、ファイルが見つからずにクラッシュしていることを示しています。
エラーの原因
1. .env
の読み込み処理が GO_ENV=prod
でも実行されていた
Go のコード内で .env
を読み込む処理が含まれていました。
if os.Getenv("GO_ENV") == "dev" {
err := godotenv.Load()
if err != nil {
log.Fatal(err)
}
}
このコードは GO_ENV=dev
のときのみ .env
を読み込むはずですが、実際には GO_ENV
が正しく設定されていないか、空の状態だったため .env
を読み込もうとしてエラーになりました。
2. GO_ENV
の環境変数が正しく設定されていなかった
ECS のタスク定義では以下のように GO_ENV=prod
を設定していましたが、実際のコンテナ内では設定されていなかった可能性があります。
ECSのタスク定義(Terraform)
"environment": [
{
"name": "GO_ENV",
"value": "prod"
}
]
しかし、ECS のデプロイ後にコンテナ内で GO_ENV
を確認すると、設定されていない(""
になっている)ことがありました。
コンテナに入って確認
aws ecs execute-command --cluster my-ecs-cluster --task タスクID --container my-app-repo --command "/bin/sh" --interactive
コンテナ内で実行
echo $GO_ENV
GO_ENV
が空のままだった場合、 .env
の読み込み処理が実行され、エラーが発生することになります。
3. .env
に依存せずに環境変数を利用するべきだった
ECS では環境変数を .env
ではなく、ECS のタスク定義 (environment
) に直接設定するのが一般的です。そのため、Go のコードで .env
を読み込む必要はありませんでした。
解決策
1. .env
の読み込み処理を削除する
最も簡単な対策は、.env
の読み込みを削除し、環境変数のみに依存するようにすることです。
修正前
if os.Getenv("GO_ENV") == "dev" {
err := godotenv.Load()
if err != nil {
log.Fatal(err)
}
}
修正後
// `.env` を読み込む処理を削除
func NewDB() {
url := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True",
os.Getenv("MYSQL_USER"),
os.Getenv("MYSQL_PW"),
os.Getenv("MYSQL_HOST"),
os.Getenv("MYSQL_PORT"),
os.Getenv("MYSQL_DB"))
var err error
DB, err = gorm.Open(mysql.Open(url), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
fmt.Println("Connected")
}
この変更により、 ECS でも .env
ファイルが不要になり、エラーが解消されます。
2. GO_ENV=prod
が正しく設定されているか確認
ECS で環境変数が正しく適用されているか確認するには、次のコマンドを実行します。
aws ecs describe-tasks --cluster my-ecs-cluster --tasks $(aws ecs list-tasks --cluster my-ecs-cluster --query 'taskArns[0]' --output text) --query 'tasks[0].containers[0].environment'
ここに GO_ENV=prod
が含まれているかチェックしてください。
もし GO_ENV
がない場合は、Terraform でタスク定義を適用し直します。
terraform apply -auto-approve
aws ecs update-service --cluster my-ecs-cluster --service my-ecs-service --force-new-deployment
3. ECS の環境変数設定を見直す
ECS のタスク定義に GO_ENV=prod
を明示的に追加します。
Terraform の ECS タスク定義
"environment": [
{
"name": "GO_ENV",
"value": "prod"
},
{
"name": "MYSQL_USER",
"value": "myuser"
},
{
"name": "MYSQL_PW",
"value": "${jsondecode(data.aws_secretsmanager_secret_version.rds_password_v5.secret_string)[\"password\"]}"
},
{
"name": "MYSQL_HOST",
"value": "${aws_db_instance.rds_instance.endpoint}"
}
]
Terraform を適用後、ECS のタスクを強制再デプロイすることで、環境変数が適用されます。
aws ecs update-service --cluster my-ecs-cluster --service my-ecs-service --force-new-deployment
まとめ
エラーの原因
-
.env
の読み込み処理が実行されていた -
GO_ENV=prod
が適用されていなかった -
.env
に依存するコードになっていた
解決策
-
.env
の読み込み処理を削除 -
GO_ENV=prod
を ECS のタスク定義に明示的に設定 - Terraform を適用後、ECS タスクを再デプロイ
この対応を行うことで、 ECS 環境で .env
に依存せずに動作するようになり、エラーが解消できました。