Docker部署Rails报ActiveRecord数据库连接失败问题排查
Rails Docker部署数据库连接失败排查方案
报错ActiveRecord::ConnectionNotEstablished提示主机名解析失败,核心原因是app容器无法定位到PostgreSQL服务,你配置的自定义桥接网络本身没有问题,按以下步骤逐一排查修复:
1. 先验证容器间网络连通性
先排除基础网络故障,执行命令进入app容器测试DNS解析:
docker-compose exec app sh ping -c 3 database
- 如果ping失败,执行
docker-compose down清理旧网络和容器,再执行docker-compose up -d重建环境重试,你当前的网络配置语法正确,大概率是旧缓存导致配置未生效 - 如果ping能拿到database容器的IP,直接进入下一步检查配置
2. 修正数据库连接主机配置
Docker自定义桥接网络内置DNS服务,同一网络下的容器只能通过docker-compose中定义的服务名互相访问,你现在的PostgreSQL服务名是database,所以Rails的数据库连接host必须填这个值:
- 打开项目
config/database.yml,确认production环境下的host字段值为database,禁止填localhost、127.0.0.1——这两个地址指向app容器自身,根本访问不到数据库容器 - 检查项目根目录的
.env文件,如果存在DATABASE_HOST变量,值也必须设置为database,避免环境变量覆盖yml配置
正确的production段database.yml配置参考:
production: adapter: postgresql encoding: unicode pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> database: <%= ENV.fetch("DB_NAME") { "your_app_production" } %> username: <%= ENV.fetch("DB_USER") { "postgres" } %> password: <%= ENV.fetch("DB_PASSWORD") { "" } %> host: database port: 5432
3. 修复启动时序问题
depends_on配置仅控制容器启动顺序,不会等待PostgreSQL完成初始化就绪,app容器如果在数据库还没启动完的时候尝试连接,也会抛出同类错误,做两处修改:
第一,修改docker-compose.yml,给数据库加健康检查,让app服务等数据库真正就绪后再启动:
services: app: # 原有app配置保留,修改depends_on段 depends_on: database: condition: service_healthy database: image: postgres:13.7 # 新增健康检查配置 healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres}"] interval: 5s timeout: 5s retries: 5 # 原有database配置保留
第二,修改你的entrypoints/docker-entrypoint.sh入口脚本,在执行Rails相关命令前增加等待数据库就绪的逻辑:
#!/bin/sh set -e # 等待PostgreSQL端口可通 until nc -z database 5432; do echo "PostgreSQL未就绪,1秒后重试..." sleep 1 done # 原有脚本逻辑保留 exec "$@"
4. 重建环境验证
所有配置修改完成后,执行命令清理旧容器、重建镜像启动:
docker-compose down -v docker-compose up -d --build
容器全部启动后,再执行迁移命令即可正常连接数据库:
docker-compose exec app bundle exec rails db:setup db:migrate
内容的提问来源于stack exchange,提问作者htamayo
相关产品推荐
相关产品推荐

