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

无法通过psycopg2.connect连接VM中Docker容器内的PostgreSQL

问题:Docker容器内Python服务无法稳定连接PostgreSQL数据库

错误信息

连接PostgreSQL时持续报错:

Failed to connect to PostgreSQL: connection to server at "postgres" (container's IP), port 5432 failed: Connection refused
        Is the server running on that host and accepting TCP/IP connections?

环境配置

docker-compose.yml 配置

version: "3.8"
services:

  postgres:
    image: postgres
    restart: always
    ports: 
      - "5432:5432"
    environment:
      - DATABASE_HOST=IP  # 注:IP为虚拟机自身IP
      - POSTGRES_USER=pids
      - POSTGRES_PASSWORD=pids

  ingesta:
    build:
      context: .
      dockerfile: datos_est/Dockerfile
    depends_on:
      - postgres

ingesta服务Dockerfile

FROM python:3.8

WORKDIR /app

COPY datos_est/example.py datos_est/example.csv /app/

RUN pip install psycopg2

CMD ["python3", "example.py"]

example.py连接代码

conexion = psycopg2.connect(
    host="postgres",
    database="postgres",
    user="pids",
    password="pids",
)

目录结构

P3/
└── src/
    ├── docker-compose.yml
    └── datos_est/
        ├── Dockerfile
        ├── example.csv
        └── example.py

已执行的排查步骤

  • 通过docker compose up启动服务,ingesta服务已配置depends_on依赖postgres
  • 在Python连接代码前添加time.sleep(10),但无法保证每次连接成功
  • 确认Python代码中host参数与Docker Compose中PostgreSQL服务名称一致
  • 清理所有容器和镜像:
    docker container rm -f $(docker container ls -aq)
    docker image rm -f $(docker image ls -q) 
    
  • 虚拟机终端可正常连接数据库:
    ubuntu@pids-vm:~/P3/src$ psql -h localhost -U pids -d pids -p 5432
    Password for user pids: 
    psql (14.9 (Ubuntu 14.9-0ubuntu0.22.04.1), server 16.1 (Debian 16.1-1.pgdg120+1))
    WARNING: psql major version 14, server major version 16.
             Some psql features might not work.
    Type "help" for help.
    
    pids=# 
    
  • 确认PostgreSQL监听5432端口:
    ubuntu@pids-vm:~/P3/src$ netstat -nl |grep 5432
    tcp        0      0 0.0.0.0:5432            0.0.0.0:*               LISTEN     
    tcp6       0      0 :::5432                 :::*                    LISTEN  
    

问题分析与解决建议

核心问题

depends_on仅保证容器启动顺序,不保证数据库服务完全就绪。PostgreSQL进程启动后需要时间初始化并开始接受连接,ingesta容器启动后立即执行脚本时,数据库可能还未准备好,导致连接拒绝。

具体解决方法

  1. 用动态等待替代固定sleep
    在Python脚本中实现循环检测连接,直到成功再继续:

    import psycopg2
    import time
    
    def wait_for_postgres():
        while True:
            try:
                conexion = psycopg2.connect(
                    host="postgres",
                    database="postgres",
                    user="pids",
                    password="pids",
                )
                conexion.close()
                print("数据库连接成功")
                break
            except psycopg2.OperationalError:
                print("数据库尚未就绪,等待1秒后重试...")
                time.sleep(1)
    
    wait_for_postgres()
    # 后续CSV导入代码
    
  2. 配置Docker健康检查
    为postgres服务添加健康检查,让ingesta仅在数据库就绪后启动:
    修改docker-compose.yml中postgres服务:

    postgres:
      image: postgres
      restart: always
      ports: 
        - "5432:5432"
      environment:
        - POSTGRES_USER=pids
        - POSTGRES_PASSWORD=pids
        # 移除无用的DATABASE_HOST变量,容器内部不需要该参数
      healthcheck:
        test: ["CMD-SHELL", "pg_isready -U pids -d postgres"]
        interval: 5s
        timeout: 5s
        retries: 5
    

    同时修改ingesta服务的依赖配置:

    ingesta:
      build:
        context: .
        dockerfile: datos_est/Dockerfile
      depends_on:
        postgres:
          condition: service_healthy
    
  3. 统一数据库名称
    终端连接的是pids数据库,但Python代码连接的是默认postgres库。若需使用pids库,需在postgres服务中添加环境变量创建该库:

    postgres:
      # ...其他配置
      environment:
        - POSTGRES_USER=pids
        - POSTGRES_PASSWORD=pids
        - POSTGRES_DB=pids
    

    并修改Python代码中的数据库参数:

    conexion = psycopg2.connect(
        host="postgres",
        database="pids",
        user="pids",
        password="pids",
    )
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 13:37:50