DigitalOcean中环境变量无法生效的问题求助
解决Rails应用无法读取环境变量的问题
针对你在Ubuntu 18.04 + Nginx + Puma + Capistrano环境下遇到的环境变量不生效问题,我整理了几个经过验证的可行方案,按推荐优先级排序:
方案1:通过Capistrano直接管理环境变量(最适配你的部署流程)
因为你用Capistrano部署,这是最直接且不易出错的方式:
方法A:使用
capistrano-dotenv插件- 在项目的
Gemfile中添加:gem 'capistrano-dotenv', require: false - 在
Capfile中加载插件:require 'capistrano/dotenv' - 在项目根目录创建
.env.production文件,写入你的环境变量:MY_VAR=your_value_here ANOTHER_VAR=another_value - 确保这个文件被Capistrano同步到服务器,部署时插件会自动让Puma加载这些变量。
- 在项目的
方法B:手动在
deploy.rb中设置默认环境
如果不想用插件,直接在config/deploy.rb里添加:set :default_env, { 'MY_VAR' => 'your_value_here', 'ANOTHER_VAR' => 'another_value' }这样Capistrano在启动Puma时会自动注入这些环境变量。
方案2:配置Puma系统服务的环境变量
如果Puma是以systemd服务运行的(Capistrano通常会生成这样的服务文件),直接在服务配置中添加环境变量:
- 找到Puma的服务文件,通常路径是
/etc/systemd/system/puma_your_app_production.service(具体名称根据你的应用和环境调整) - 编辑这个文件,在
[Service]区块下添加:
或者如果变量较多,可以用Environment="MY_VAR=your_value_here" Environment="ANOTHER_VAR=another_value"EnvironmentFile指向一个文件:EnvironmentFile=/path/to/your/env/file - 保存文件后,重新加载systemd配置并重启Puma:
这种方式能确保Puma进程启动时直接读取到变量,不受shell会话影响。sudo systemctl daemon-reload sudo systemctl restart puma_your_app_production
方案3:使用dotenv-rails gem(Rails项目内管理)
这个gem可以让Rails直接从项目内的.env文件读取变量:
- 在
Gemfile的:production组中添加:group :production do gem 'dotenv-rails' end - 在项目根目录创建
.env.production文件,写入你的环境变量 - 确保这个文件被包含在Capistrano的部署文件列表中(默认如果不是.gitignore的话会被同步,或者在
deploy.rb中添加append :linked_files, '.env.production'让它成为共享文件) - 部署后,Rails启动时会自动加载这个文件里的变量。
为什么之前的方法没生效?
.bashrc、.profile、.bash_profile:这些文件只在交互式SSH会话中加载,Nginx和Puma作为后台系统服务运行时,不会启动交互式shell,所以根本不会读取这些文件。/etc/environment:这个文件由PAM模块加载,但systemd服务默认不会自动读取它,除非服务配置中明确配置了PAMName=login或者使用了EnvironmentFile指向它,所以你终端能echo但服务读不到。
内容的提问来源于stack exchange,提问作者Mani
相关产品推荐
相关产品推荐

