Rails 7无法从环境变量读取数据库密码问题排查求助
Rails 7.0.4.3 容器部署中数据库密码为nil的排查与解决
问题场景
我有一个Rails 7.0.4.3应用,部署在远程服务器的Docker容器中,启动时出现数据库连接错误,提示无密码提供。容器控制台和rails控制台中能正常获取到DATABASE_PASSWORD环境变量,但执行Rails.configuration.database_configuration后,对应环境的password值始终为nil。
database.yaml配置
default: &default adapter: postgresql encoding: unicode pool: 10 postgis_schema: public schema_search_path: public,postgresql host: <%= ENV.fetch("DATABASE_HOST") { "localhost" } %> port: <%= ENV.fetch("DATABASE_PORT") { 5432 } %> username: <%= ENV.fetch("DATABASE_USERNAME") { %x(whoami).strip } %> password: <%= ENV.fetch("DATABASE_PASSWORD") { "password" } %> development: <<: *default username: 'postgres' password: 'password' database: <%= "#{ENV['PROJECT_NAME']}_development" %> test: <<: *default username: 'postgres' password: 'password' database: <%= "#{ENV['PROJECT_NAME']}_test" %> staging: <<: *default database: <%= "#{ENV['PROJECT_NAME']}_staging" %> production: <<: *default database: <%= "#{ENV['PROJECT_NAME']}_production" %> dev_remote: <<: *default database: <%= "#{ENV['PROJECT_NAME']}_dev_remote" %>
启动错误日志
rails aborted! ActiveRecord::ConnectionNotEstablished: connection to server at "REDACTED", port 5438 failed: fe_sendauth: no password supplied Caused by: PG::ConnectionBad: connection to server at "REDACTED", port 5438 failed: fe_sendauth: no password supplied
配置检查结果
执行Rails.configuration.database_configuration输出(关键部分):
=> {"default"=>{"adapter"=>"postgresql", "encoding"=>"unicode", "pool"=>10, "postgis_schema"=>"public", "schema_search_path"=>"public,postgresql", "host"=>"REDACTED", "port"=>5438, "username"=>"user"}, "staging"=>{"adapter"=>"postgresql", "encoding"=>"unicode", "pool"=>10, "postgis_schema"=>"public", "schema_search_path"=>"public,postgresql", "host"=>"REDACTED", "port"=>5438, "username"=>"user", "database"=>"project_staging"}, "production"=>{"adapter"=>"postgresql", "encoding"=>"unicode", "pool"=>10, "postgis_schema"=>"public", "schema_search_path"=>"public,postgresql", "host"=>"REDACTED", "port"=>5438, "username"=>"user", "database"=>"project_production"}, "dev_remote"=>{"adapter"=>"postgresql", "encoding"=>"unicode", "pool"=>10, "postgis_schema"=>"public", "schema_search_path"=>"public,postgresql", "host"=>"REDACTED", "port"=>5438, "username"=>"user", "database"=>"project_dev_remote", "password"=>nil}}
Dockerfile配置
FROM ruby:3.1.4-alpine RUN apk add --update --no-cache bash build-base postgresql-dev tzdata git openssh ssmtp nano WORKDIR /myapp ENV RAILS_ENV $RAILS_ENV COPY Gemfile /myapp/Gemfile COPY Gemfile.lock /myapp/Gemfile.lock RUN gem install bundler -v 2.2.32 && bundle config set --local without 'development test' && bundle install -j $(nproc) COPY . /myapp RUN chmod +x /myapp/start-app.sh CMD /myapp/start-app.sh
排查与解决步骤
直接验证ERB渲染结果
在容器内执行以下命令,查看database.yaml经过ERB渲染后的原始内容,确认password字段是否正确填充:erb config/database.yaml如果渲染后的password为空或异常,说明ERB解析或环境变量传递存在问题;如果渲染结果正确,问题则出在Rails加载配置的环节。
修复YAML解析的特殊字符问题
如果数据库密码包含&、#、空格等YAML特殊字符,未加引号的字符串可能被解析错误,导致password变为nil。修改database.yaml中的password行,强制用引号包裹:password: "<%= ENV.fetch("DATABASE_PASSWORD") { "password" } %>"检查Rails配置加载逻辑
- 确认当前运行的
RAILS_ENV,执行echo $RAILS_ENV验证环境是否匹配预期。 - 在对应环境的rails控制台中,执行
ActiveRecord::Base.configurations[Rails.env],再次确认password字段值。 - 检查
config/initializers/目录下的文件,是否有代码修改了数据库配置。
- 确认当前运行的
确认Docker环境变量传递完整性
- 检查启动容器的命令(或docker-compose配置),确保
DATABASE_PASSWORD被正确传递到容器内。 - 查看
start-app.sh脚本内容,确认启动Rails进程时没有覆盖或丢失环境变量,建议用exec命令启动Rails,确保环境变量继承:exec bundle exec rails server -b 0.0.0.0
- 检查启动容器的命令(或docker-compose配置),确保
清理Rails配置缓存
生产/预发布环境下Rails会缓存配置文件,若之前的空配置被缓存,会导致问题。执行以下命令清理缓存:rm -rf tmp/cache重启容器后再验证配置。
内容的提问来源于stack exchange,提问作者Vi.
相关产品推荐
相关产品推荐

