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

Docker运行Python脚本时PostgreSQL连接失败问题排查

问题:Docker运行Python连接PostgreSQL时出现连接拒绝错误

我编写了一段简单的Python代码(main.py),使用psycopg2连接PostgreSQL数据库,本地执行python main.py时能正常返回“Success!”,但通过Docker构建镜像并运行时,出现psycopg2.OperationalError连接拒绝错误。

Python代码(main.py)

import psycopg2

postgres_credentials = {
    "host": "postgres_mcdonalds",
    "database_name": "postgres",
    "user": "postgres",
    "password": "password"
}

filename = "FastFoodNutritionMenu.csv"

conn = psycopg2.connect(
    host=postgres_credentials["host"],
    database=postgres_credentials["database_name"],
    user=postgres_credentials["user"],
    password=postgres_credentials["password"],
    port="5432",
)
print("Sucess!")

Dockerfile配置

FROM python:3

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

COPY . .

RUN pip install -r requirements.txt

CMD ["python", "main.py"]

PostgreSQL的Docker Compose配置

services:
  postgres_mcdonalds:
    image: postgres:14.5
    environment:
      POSTGRES_PORT: "5432"
      POSTGRES_USER: "postgres"
      POSTGRES_PASSWORD: "password"
      PORT : "5432"
      TZ: America/Sao_Paulo
    ports:
      - "5432:5432"
    volumes:
      - postgres_volume:/var/lib/postgres
    
volumes:
  postgres_volume:

执行命令及报错信息

执行命令:

docker build -t test_postgres .
docker run test_postgres

报错信息:

Traceback (most recent call last):
  File "//main.py", line 14, in <module>
    conn = psycopg2.connect(
           ^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/psycopg2/__init__.py", line 122, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
psycopg2.OperationalError: connection to server at "localhost" (127.0.0.1), port 5432 failed: Connection refused
        Is the server running on that host and accepting TCP/IP connections?
connection to server at "localhost" (::1), port 5432 failed: Cannot assign requested address
        Is the server running on that host and accepting TCP/IP connections?

原因及解决方法
  • 核心问题:网络隔离
    你用docker run单独启动的Python容器,和通过Compose启动的PostgreSQL容器不在同一个Docker网络中。Compose默认会创建专属网络,而单独docker run的容器默认使用bridge网络,两个网络无法通过服务名(postgres_mcdonalds)通信。Python容器无法解析该主机名,会 fallback 到localhost,而容器内部的localhost和宿主机的localhost不是同一概念,因此连接被拒绝。

  • 解决步骤

    1. 将Python服务加入到Compose配置中,让所有服务处于同一网络:
      修改Compose文件如下:
      services:
        postgres_mcdonalds:
          # 保留原PostgreSQL配置
          image: postgres:14.5
          environment:
            POSTGRES_USER: "postgres"
            POSTGRES_PASSWORD: "password"
            TZ: America/Sao_Paulo
          ports:
            - "5432:5432"
          volumes:
            - postgres_volume:/var/lib/postgres
        
        python_app:
          build: .
          depends_on:
            - postgres_mcdonalds
          # 可选:用环境变量传递数据库配置,避免代码硬编码
          environment:
            POSTGRES_HOST: postgres_mcdonalds
            POSTGRES_DB: postgres
            POSTGRES_USER: postgres
            POSTGRES_PASSWORD: password
      volumes:
        postgres_volume:
      
    2. 执行docker-compose up --build启动所有服务,此时Python容器可通过postgres_mcdonalds主机名正常访问PostgreSQL。
  • 额外注意事项

    • depends_on仅保证PostgreSQL容器先启动,不保证数据库服务完全就绪。若需确保数据库可用,可添加健康检查或使用等待脚本。
    • PostgreSQL Compose配置中的POSTGRES_PORT和PORT环境变量无实际作用,PostgreSQL默认监听5432端口,无需额外配置。
    • 本地运行成功是因为宿主机可通过localhost访问Compose映射的5432端口,但Docker容器内部的localhost指向容器自身,而非宿主机。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 00:46:33