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

Compute Engine上Docker容器PostgreSQL连接超时问题求助

问题:Node.js API容器无法连接虚拟机中的PostgreSQL容器

我正在开发一个基于PostgreSQL和Node.js Express的Web应用,已将其容器化并推送至Artifact Registry,且已将相关镜像拉取至虚拟机中。我的docker-compose文件配置如下:

services:
    postgres:
        image: postgres:latest
        container_name: postgres
        environment:
            POSTGRES_DB: web_app_db
            POSTGRES_USER: developer
            POSTGRES_PASSWORD: test1234
        ports:
            - "5432:5432"
        volumes:
            - postgres-data:/var/lib/postgresql/data
        network:
            - my-nw
    api:
        image: web-api 
        command: >
            sh -c '
                npm run upgrade-docker &&
                if [ "$SEED" = "true" ]; then
                    npm run seed-roles ./src/environments/.env.docker &&
                    npm run seed-stores ./src/environments/.env.docker &&
                    npm run seed-products ./src/environments/.env.docker
                fi &&
                npm run start ./src/environments/.env.docker
            '
        environment:
            - WORKDIR=$PWD
            - PORT=80
            - SEED=true
        volumes:
            - ./src:/app/src
            - ./dist:/app/dist
        depends_on:
            - postgres
        network:
            - my-nw
networks:
  my-nw:
    driver: bridge

volumes:
    postgres-data:

执行docker compose up -d postgres后,PostgreSQL服务正常启动并暴露5432端口;但执行docker compose up api时,Web API启动后无法连接PostgreSQL,最终出现连接超时错误:

api  | Error: connect ETIMEDOUT 172.22.0.2:5432
api  |     at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1555:16) {
api  |   errno: -110,
api  |   code: 'ETIMEDOUT',
api  |   syscall: 'connect',
api  |   address: '172.22.0.2',
api  |   port: 5432
}

我已尝试将API容器中的数据库主机名从postgres改为0.0.0.0、localhost,也尝试使用默认网络替代自定义my-nw网络,但均无效。可以通过主机机器执行psql -U developer -h localhost -p 5432连接PostgreSQL,且该docker-compose文件在本地机器可正常运行,但在虚拟机中失败,请问是否存在配置遗漏?


排查与解决建议

1. 修正docker-compose网络配置语法错误

你的docker-compose文件中,postgres和api服务里的network字段是单数,正确语法应为复数networks。将两处network: - my-nw修改为networks: - my-nw,否则容器无法加入自定义的my-nw网络,导致服务名无法解析通信。

2. 等待PostgreSQL服务就绪后再启动API

depends_on仅保证postgres容器启动,不确保PostgreSQL服务完全就绪。虚拟机性能可能弱于本地,数据库启动较慢,API启动时数据库还未准备好就会超时。可以:

  • 在API启动命令中加入等待逻辑,比如使用wait-for-it脚本:
    修改api的command为:
    sh -c '
        wait-for-it postgres:5432 -t 30 &&
        npm run upgrade-docker &&
        if [ "$SEED" = "true" ]; then
            npm run seed-roles ./src/environments/.env.docker &&
            npm run seed-stores ./src/environments/.env.docker &&
            npm run seed-products ./src/environments/.env.docker
        fi &&
        npm run start ./src/environments/.env.docker
    '
    
    确保wait-for-it脚本已包含在web-api镜像中,或通过volume挂载到容器内。
  • 在Node.js代码中添加数据库连接重试逻辑,直到连接成功。

3. 确认PostgreSQL监听配置

进入postgres容器检查监听地址:

docker exec -it postgres bash
grep listen_addresses /var/lib/postgresql/data/postgresql.conf

正常应返回listen_addresses = '*',确保PostgreSQL允许所有地址连接。

4. 检查虚拟机防火墙规则

虚拟机的iptables或安全组可能拦截容器间的网络流量。确认docker网段(如172.22.0.0/16)的入站/出站规则允许通信。

5. 验证API的数据库连接配置

确保.env.docker文件中数据库主机配置为postgres(服务名),而非IP或localhost。在docker自定义网络中,服务名会被自动解析为对应容器的IP,这是容器间通信的正确方式。

6. 检查容器网络归属

执行以下命令查看容器所属网络:

docker inspect postgres | grep Networks
docker inspect api | grep Networks

确认两个容器都加入了my-nw网络,否则服务名无法解析。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 14:27:02