无法通过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容器启动后立即执行脚本时,数据库可能还未准备好,导致连接拒绝。
具体解决方法
用动态等待替代固定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导入代码配置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统一数据库名称
终端连接的是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
相关产品推荐
相关产品推荐

