You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS ECS部署Rails应用:环境变量合并引发文件路径过长错误

在AWS ECS部署Rails应用时Secrets Manager环境变量合并问题的解决

问题描述

在AWS ECS上部署Ruby on Rails应用,用AWS Secrets Manager管理环境变量时出现异常:调用ENV["RAILS_ENV"]返回的不是预期的production字符串,而是包含所有Secret变量的JSON哈希(格式如{"RAILS_ENV": "production", "JWT_SECRET":"xxx", ...}),启动应用时触发以下错误:

File name too long @ rb_sysopen - /app/.env.
{
"RAILS_ENV": "production",
"JWT_SECRET":"xxx",
...
}
.local (Errno::ENAMETOOLONG)

推测是某环境变量被用于配置文件访问时,因内容过长导致路径解析错误。核心疑问:为何环境变量会被合并成一个哈希而非单独设置?

原因分析

这是因为在ECS配置Secrets Manager时,错误地将整个Secret的JSON字符串赋值给了单个环境变量(此处为RAILS_ENV),而非将Secret中的每个键值对映射为独立的环境变量。ECS默认不会自动解析Secret的JSON内容,若配置时选择了「Set as single value」模式,而非「Secrets」模式下的逐个键映射,就会出现所有Secret内容被塞进一个环境变量的情况。

现有解决方案

在config/boot.rb中,ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)代码之前添加以下代码,手动解析JSON哈希并拆分到对应环境变量:

require 'aws-sdk-secretsmanager'
if ENV['RAILS_ENV'] && ENV['RAILS_ENV'] != "development"
    secret_hash = JSON.parse(ENV['RAILS_ENV'])
    ENV['JWT_SECRET'] = secret_hash['JWT_SECRET']
    ENV['RAILS_ENV'] = secret_hash['RAILS_ENV']
    # 按需添加其他需要的环境变量
end

该方案可临时解决问题,但需要手动维护变量映射,扩展性较差。

更优方案推荐

方案1:ECS任务定义中直接映射Secret键到环境变量

在ECS任务定义的容器配置里,选择「Secrets」而非普通的「Environment variables」模式,将Secret中的每个键(如RAILS_ENV、JWT_SECRET)分别映射为独立的环境变量:

  • 对每个需要的变量,设置Name为环境变量名,ValueFrom为Secret的ARN加上键路径,格式为arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-name>:<key>::
  • 示例:Name: RAILS_ENV, ValueFrom: arn:aws:secretsmanager:us-east-1:1234567890:secret:my-rails-secrets:RAILS_ENV::

这种方式下ECS会自动将Secret中的每个键值对解析为单独的环境变量,无需修改应用代码。

方案2:使用ECS启动脚本自动注入环境变量

在ECS任务的容器启动命令中添加预处理脚本,拉取Secret并自动解析为环境变量:

  1. 创建shell脚本(如load-secrets.sh):
#!/bin/bash
# 拉取Secret内容
SECRET=$(aws secretsmanager get-secret-value --secret-id my-rails-secrets --query SecretString --output text)
# 将JSON键值对转为export命令并执行
echo "$SECRET" | jq -r 'to_entries|map("export \(.key)=\(.value|tostring)")|.[]' > /tmp/secrets.sh
source /tmp/secrets.sh
# 启动Rails应用
exec "$@"
  1. 在ECS任务定义中,将容器启动命令设置为:["/bin/bash", "/app/load-secrets.sh", "rails", "server"]
  2. 确保容器拥有Secrets Manager的secretsmanager:GetSecretValue权限

这种方式无需修改Rails代码,且能自动同步Secret中的所有变量,适合变量较多的场景。

内容的提问来源于stack exchange,提问作者Louis Daisomont

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 11:15:38