Docker Compose构建Rails容器时,连接Gemstash服务被拒绝
看起来你遇到的是Docker容器间网络连通性的典型问题——尤其是在build阶段(而非容器运行阶段)访问另一个容器时容易踩坑。我来帮你一步步排查解决:
1. 别再用localhost了!这是核心问题
你在Dockerfile里配置Gemstash地址时,如果写的是http://localhost:9292,那肯定会失败。因为在docker-compose build过程中,localhost指向的是正在构建的app容器本身,而不是宿主机或者Gemstash容器。
针对不同场景替换地址:
如果Gemstash是同一个docker-compose.yml里的服务:
直接用Gemstash的服务名作为地址,比如http://gemstash:9292(假设你的Gemstash服务名是gemstash)。Docker Compose会自动在内部网络中解析服务名为对应容器的IP。如果Gemstash是单独启动的容器:
用宿主机的内网IP地址(比如192.168.1.100)代替localhost,比如http://192.168.1.100:9292。别用127.0.0.1,同样会指向build容器自身。
2. 确保Build阶段能访问到Compose网络(同Compose场景)
即使你用了服务名,默认情况下docker-compose build的容器不会加入到Compose创建的专属网络里,所以还是解析不了服务名。你需要在docker-compose.yml里给app服务配置build网络:
services: gemstash: image: rubygems/gemstash ports: - "9292:9292" volumes: - gemstash-data:/var/gemstash app: build: context: . # 指定使用Compose默认网络(默认是<项目目录名>_default) network: ${COMPOSE_PROJECT_NAME}_default # 其他配置... volumes: gemstash-data:
这样build时,app的临时构建容器就会加入到Compose的网络中,就能通过服务名访问Gemstash了。
3. 验证Gemstash是否监听了正确的地址
有时候Gemstash默认只监听127.0.0.1,这样容器外部(包括其他容器)根本访问不了。你可以进入Gemstash容器检查:
docker exec -it <你的Gemstash容器ID> netstat -tulpn
如果看到9292端口的监听地址是127.0.0.1,就修改Gemstash的启动命令,让它监听所有网卡:
# 重启Gemstash容器时用这个命令 gemstash start --bind 0.0.0.0
或者在Gemstash的配置文件里设置bind: 0.0.0.0,确保外部能访问。
4. 给Dockerfile加个连通性测试
为了快速定位问题,你可以在Dockerfile的bundle install前加一条curl命令,验证Gemstash是否可达:
# 配置Gemstash镜像 RUN bundle config set mirror.https://rubygems.org http://gemstash:9292 # 测试连通性,失败时会终止build并输出详细信息 RUN curl -v http://gemstash:9292 # 执行bundle install RUN bundle install --without development test
这样build时如果连接失败,你能直接看到是DNS解析错误还是连接被拒绝,更容易排查。
最后检查防火墙
如果以上都没问题,看看宿主机的防火墙是不是阻止了Docker容器之间的通信。Docker默认的内网网段一般是172.17.0.0/16或192.168.x.x,确保防火墙允许这个网段的流量。
内容的提问来源于stack exchange,提问作者ZedTuX

