GitLab CI环境下Docker Compose容器内服务连接字符串的正确使用及连接失败问题排查
你的思路完全没问题——Docker Compose默认会给所有服务搭一个共享网络,服务名(比如server)本来就应该能直接当域名用,同一网络里的容器都能解析到。但访问失败通常是几个常见的小坑导致的,咱们一步步捋:
1. 先查Server应用的监听地址(最常见的坑!)
如果你的server app只绑定了localhost(也就是127.0.0.1),那只有容器自己能访问,同一网络的tests容器根本连不上。
你得改一下server的配置,让它监听0.0.0.0(所有可用的网络接口):
- 要是Node.js app,启动命令改成
app.listen(3100, '0.0.0.0') - 要是Python Flask,就用
app.run(host='0.0.0.0', port=3100) - 其他语言/framework同理,核心就是别只绑定localhost
你的健康检查用http://localhost:3100能成功,这刚好说明容器内部访问没问题,但也侧面印证了app可能只绑了localhost,导致外部容器访问不了。
2. 先调试下容器间的DNS解析
可以在tests容器的启动脚本里加俩命令,看看能不能找到server的IP:
# 可以加到tests.Dockerfile的CMD里,或者CI的script阶段临时调试 ping -c 3 server nslookup server
要是解析失败,咱们就显式指定网络,避免潜在的隔离问题:
修改你的docker-compose.yml,加上自定义网络:
version: '3.9' services: tests: build: context: ./code dockerfile: tests.Dockerfile depends_on: server: condition: service_healthy networks: - app-network server: build: context: ./code dockerfile: test.server.Dockerfile ports: - "3100:3100" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3100"] interval: 1m10s timeout: 10s retries: 300 networks: - app-network networks: app-network: driver: bridge
显式定义网络能避免Compose自动创建网络时的意外问题。
3. 确认Server容器的端口真的开放了
容器间访问不用管ports里的3100:3100(那是给宿主机用的),只要server app在容器内部监听了3100端口就行。你可以在server容器里跑个命令看看:
# 进入server容器执行 netstat -tulpn | grep 3100
要是看不到0.0.0.0:3100的记录,说明app没正确绑定端口。
4. GitLab CI环境的小细节
你用的是docker:dind服务,所有容器都跑在DinD的Docker daemon里,和Runner宿主机是隔离的,但Compose的网络规则还是生效的。只要确保:
- DinD服务正常启动,你的
DOCKER_HOST配置tcp://docker:2375是对的 - 没有防火墙规则挡住容器间的通信
最后总结
大概率就是server app只监听了localhost,改成0.0.0.0应该就能解决。要是还不行,先通过调试命令确认DNS解析和端口监听的情况,一步步排查就好。
内容的提问来源于stack exchange,提问作者sebastianspiller

