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

Docker化Rails应用向同环境Rails服务发起HTTP请求失败

环境信息
drmanabase ➜ /app (002-build-seed-file ✗) $ ruby -v
ruby 3.1.0p0 (2021-12-25 revision fb4df44d16) [x86_64-linux]
drmanabase ➜ /app (002-build-seed-file ✗) $ rails -v
Rails 7.0.2.3
问题背景

通过Dockerfile、docker-compose.yml和devcontainer.json搭建了两个Rails/Postgres容器化应用:

  • 「public应用」:存放无需保密的业务逻辑;
  • 「private应用」:存放需保密的业务逻辑,作为HTTP服务接收请求并返回响应。

private应用的基础Rails结构已搭建完成,本地浏览器访问localhost:3000可正常显示页面,但从public应用容器内执行以下代码发起请求时失败:

require 'net/http'
require 'uri'

uri = URI('http://localhost:3000/')

Net::HTTP.get(uri)

报错信息

/usr/local/lib/ruby/3.1.0/socket.rb:1214:in `__connect_nonblock': Failed to open TCP connection to localhost:3000 (Cannot assign requested address - connect(2) for [::1]:3000) (Errno::EADDRNOTAVAIL)
        from /usr/local/lib/ruby/3.1.0/socket.rb:1214:in `connect_nonblock'
        from /usr/local/lib/ruby/3.1.0/socket.rb:56:in `connect_internal'
        from /usr/local/lib/ruby/3.1.0/socket.rb:137:in `connect'
        from /usr/local/lib/ruby/3.1.0/socket.rb:642:in `block in tcp'
        from /usr/local/lib/ruby/3.1.0/socket.rb:227:in `each'
        from /usr/local/lib/ruby/3.1.0/socket.rb:227:in `foreach'
        from /usr/local/lib/ruby/3.1.0/socket.rb:632:in `tcp'
        from /usr/local/lib/ruby/3.1.0/net/http.rb:998:in `connect'
        from /usr/local/lib/ruby/3.1.0/net/http.rb:976:in `do_start'
        from /usr/local/lib/ruby/3.1.0/net/http.rb:965:in `start'
        from /usr/local/lib/ruby/3.1.0/net/http.rb:627:in `start'
        from /usr/local/lib/ruby/3.1.0/net/http.rb:503:in `get_response'
        from /usr/local/lib/ruby/3.1.0/net/http.rb:474:in `get'
        from /app/lib/mtg_json/tempCodeRunnerFile.rb:6:in `<main>'
/usr/local/lib/ruby/3.1.0/socket.rb:1214:in `__connect_nonblock': Cannot assign requested address - connect(2) for [::1]:3000 (Errno::EADDRNOTAVAIL)
        from /usr/local/lib/ruby/3.1.0/socket.rb:1214:in `connect_nonblock'
        from /usr/local/lib/ruby/3.1.0/socket.rb:56:in `connect_internal'
        from /usr/local/lib/ruby/3.1.0/socket.rb:137:in `connect'
        from /usr/local/lib/ruby/3.1.0/socket.rb:642:in `block in tcp'
        from /usr/local/lib/ruby/3.1.0/socket.rb:227:in `each'
        from /usr/local/lib/ruby/3.1.0/socket.rb:227:in `foreach'
        from /usr/local/lib/ruby/3.1.0/socket.rb:632:in `tcp'
        from /usr/local/lib/ruby/3.1.0/net/http.rb:998:in `connect'
        from /usr/local/lib/ruby/3.1.0/net/http.rb:976:in `do_start'
        from /usr/local/lib/ruby/3.1.0/net/http.rb:965:in `start'
        from /usr/local/lib/ruby/3.1.0/net/http.rb:627:in `start'
        from /usr/local/lib/ruby/3.1.0/net/http.rb:503:in `get_response'
        from /usr/local/lib/ruby/3.1.0/net/http.rb:474:in `get'
        from /app/lib/mtg_json/tempCodeRunnerFile.rb:6:in `<main>'
排查与解决方法

核心原因

容器内的localhost指向容器自身,而非宿主机或其他容器。因此public应用容器中请求localhost:3000时,实际是访问自身的3000端口,而非private应用的服务。

具体修复步骤

  1. 确认网络归属
    确保两个应用处于同一个Docker网络中。默认情况下,docker-compose会为项目创建专属网络,所有服务自动加入;如果是分开的docker-compose配置,需手动指定共享网络。

  2. 替换访问地址为服务名
    在public应用的请求代码中,将localhost替换为private应用在docker-compose.yml中定义的服务名。例如private应用的服务名为private-app,修改后的代码如下:

    require 'net/http'
    require 'uri'
    
    uri = URI('http://private-app:3000/')
    
    Net::HTTP.get(uri)
    
  3. 确保private应用绑定正确地址
    确认private应用的Rails服务绑定到0.0.0.0(允许所有网卡访问),而非默认的127.0.0.1(仅本地访问)。启动命令需改为:

    rails server -b 0.0.0.0 -p 3000
    

    也可在Dockerfile的CMD指令或docker-compose.yml的command字段中指定该启动命令。

  4. 验证网络连通性
    进入public应用容器,执行ping命令测试与private应用的连通性:

    ping private-app
    

    若能ping通则网络配置正常;若不通,检查docker-compose的网络配置是否正确。

内容的提问来源于stack exchange,提问作者Justin Simpson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 04:59:51