GitHub Actions中Docker-in-Docker无法访问容器内PostgreSQL服务
问题分析
你遇到的是典型的Docker-in-Docker(DinD)嵌套网络问题:
- GitHub Actions通过
container语法启动的外层容器,和你用tilt/docker-compose启动的内层PostgreSQL容器分属不同网络命名空间 - 内层容器实际运行在宿主机的Docker daemon上(你的self-hosted runner带
docker标签,共享宿主机Docker环境),而非外层容器内部,所以localhost:8090和服务名postgres都无法直接访问
解决方案
以下是适配你「不暴露服务到容器外部」需求的两种可行方案:
方案一:用专用Docker网络实现跨容器互通
通过创建内部Docker网络,让外层GitHub Actions容器和内层PostgreSQL容器加入同一网络,就能直接用服务名访问:
- 修改GitHub Actions配置,在Tilt步骤前创建专用网络并将当前容器加入:
build-tilt: name: Build Tilt runs-on: [ self-hosted, docker ] container: image: devitllc/coretto-build:17 steps: - name: Checkout code uses: actions/checkout@v3 - name: Setup internal CI network run: | # 创建网络(已存在则忽略) docker network create --driver bridge ci-internal || true # 将当前GitHub Actions容器加入网络 docker network connect ci-internal $HOSTNAME - name: Tilt CI run: tilt ci --timeout 15m --debug
- 修改docker-compose.yml,指定使用
ci-internal网络并移除端口映射(避免暴露到外部):
version: "3.9" services: postgres: image: postgres:14 # 移除端口映射,避免暴露到宿主机外部 # ports: # - "8090:5432" environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: test POSTGRES_DB: example volumes: - example-postgres:/var/lib/postgresql/data deploy: resources: limits: memory: 1g healthcheck: test: CMD pg_isready -U postgres interval: 5s timeout: 5s retries: 10 networks: - ci-internal volumes: example-postgres: networks: ci-internal: external: true
- 此时你可以直接用
postgres:5432访问数据库,两个容器处于同一网络内,服务名可直接解析。
方案二:通过Docker网关IP访问
如果不想修改网络配置,可直接用宿主机Docker的默认网关IP(通常为172.17.0.1)访问内层容器:
- 保留docker-compose的端口映射
- 在应用代码或测试脚本中,将数据库地址改为
172.17.0.1:8090
若宿主机Docker网关IP不是默认值,可通过docker inspect bridge | grep Gateway命令获取实际IP,在GitHub Actions步骤中动态传入。
关键注意事项
- 禁止用
localhost:外层容器的localhost指向自身,而非内层容器所在的宿主机Docker环境 - 避免端口冲突:多runner并行时,不要固定端口,可改用
"8090-8100:5432"这类端口范围,或直接移除端口映射用网络访问
内容的提问来源于stack exchange,提问作者spierce7
相关产品推荐
相关产品推荐

