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不是同一概念,因此连接被拒绝。解决步骤
- 将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: - 执行
docker-compose up --build启动所有服务,此时Python容器可通过postgres_mcdonalds主机名正常访问PostgreSQL。
- 将Python服务加入到Compose配置中,让所有服务处于同一网络:
额外注意事项
depends_on仅保证PostgreSQL容器先启动,不保证数据库服务完全就绪。若需确保数据库可用,可添加健康检查或使用等待脚本。- PostgreSQL Compose配置中的
POSTGRES_PORT和PORT环境变量无实际作用,PostgreSQL默认监听5432端口,无需额外配置。 - 本地运行成功是因为宿主机可通过localhost访问Compose映射的5432端口,但Docker容器内部的localhost指向容器自身,而非宿主机。
内容的提问来源于stack exchange,提问作者victorcd
相关产品推荐
相关产品推荐

