GitLab CI启动Docker容器后无法连接本地9000端口问题
GitLab CI 运行Node+Postgres应用9000端口连接拒绝故障解决方案
核心故障原因
- 你当前使用Docker-in-Docker(dind)模式执行CI任务,所有
docker命令实际是发送给别名docker的dind服务容器执行,而非当前运行CI脚本的job容器本地 - 你配置的
-p 9000:9000端口映射规则,是将应用容器的9000端口绑定到dind服务容器的9000端口,而非你执行curl命令的job容器的localhost端口,因此访问localhost:9000必然触发连接拒绝 - 该问题和防火墙规则、Docker桥接配置无直接关系,属于dind模式下的网络拓扑认知偏差
- 额外注意:如果Node应用默认绑定
127.0.0.1而非0.0.0.0,即使网络配置正确,容器外部也无法访问服务
前置排查步骤
- 执行
docker logs <你的应用容器ID>查看Node服务启动日志,确认服务正常启动且监听0.0.0.0:9000,无数据库连接报错 - 直接访问
http://docker:9000测试连通性:dind服务在CI网络中设置了别名docker,job容器可直接解析该域名,如果能通就确认是之前访问localhost的目标地址错误
修复方案
方案1:最小改动,直接访问dind服务的映射端口
不需要调整容器启动的网络配置,只需要把所有访问应用的地址从localhost:9000改成docker:9000,同时替换固定sleep为服务就绪轮询,避免无效等待。
修改后的test阶段脚本片段:
api-component-tests: stage: test services: - name: 'postgres:11.9' alias: postgres - name: 'docker:19.03.12-dind' alias: docker variables: POSTGRES_USER: 'postgres' POSTGRES_PASSWORD: 'password' POSTGRES_DB: 'postgres' POSTGRES_HOST_AUTH_METHOD: trust API_BASE_URL: 'http://docker:9000' script: - docker run -d -e POSTGRES_HOST=postgres -p 9000:9000 $DOCKER_TEST_IMAGE_API # 轮询等待服务就绪,每2秒检查一次,替代固定60秒sleep - until curl -s -f -o /dev/null $API_BASE_URL/health; do sleep 2; done - curl -X GET "$API_BASE_URL/rooms/1000ef5c-1657-46b2-bb36-c74080e00c01" - cd end-to-end-tests - yarn install # 确保e2e测试配置中读取API_BASE_URL变量访问接口 - yarn test
注意:这里直接传
POSTGRES_HOST=postgres即可,不需要使用旧版link生成的POSTGRES_PORT_5432_TCP_ADDR变量,GitLab CI的服务基于DNS域名解析,直接用服务别名更稳定。
方案2:共享CI网络,无需端口映射
启动应用容器时直接加入CI任务所在的内部网络,和job容器、Postgres服务处于同一网络平面,不需要做端口映射,直接通过容器别名访问:
容器启动命令修改为:
docker run -d --network $CI_JOB_NETWORK --network-alias api -e POSTGRES_HOST=postgres $DOCKER_TEST_IMAGE_API
后续访问应用的地址改为http://api:9000即可,该方案下服务互通走CI内部网络,不需要暴露端口,安全性和稳定性更高。
现有配置笔误修复
你当前的.gitlab-ci.yml存在两处明显笔误,需要同步修正:
- build阶段重复定义了两次
api-component-api任务,删除重复的任务块即可 - 第一个重复的build任务中
docker push $为无效命令,修正为docker push $DOCKER_TEST_IMAGE_API
内容的提问来源于stack exchange,提问作者Dan
相关产品推荐
相关产品推荐

