如何让Docker中的Python项目通过docker-compose访问本地PostgreSQL数据库
问题:Docker容器中Python脚本无法连接PostgreSQL数据库
背景
本地调试Python主脚本时,数据库连接函数可正常工作,但将项目通过Dockerfile和docker-compose打包进容器后,无法建立数据库连接。
数据库连接函数
# 创建数据库连接 def create_connection(host, dbname, user, password): print(host, dbname, user, password) try: conn = psycopg2.connect("host={} dbname={} user={} password={}".format(host, dbname, user, password)) conn.set_session(autocommit=True) except psycopg2.Error as e: print("Error: Could not make connection to the Postgres database") print(e) # 使用连接获取可执行查询的游标 try: cur = conn.cursor() except psycopg2.Error as e: print("Error: Could not get cursor to the Database") print(e) return conn, cur
错误信息
Error: Could not make connection to the Postgres database connection to server at "127.0.0.1", port 5432 failed: Connection refused Is the server running on that host and accepting TCP/IP connections?
当前docker-compose.yml配置
version: '3.4' networks: network1: name: my-network attachable: true ipam: driver: default config: - subnet: 172.18.0.0/16 ip_range: 172.18.5.0/24 gateway: 172.18.0.1 services: tft: image: tft build: context: . dockerfile: ./Dockerfile network_mode: host postgres: image: postgres:14.1-bullseye environment: POSTGRES_PASSWORD: "*********" ports: - "5433:5432" networks: - network1 extra_hosts: - "host.docker.internal:host-gateway"
问题根源与修复方案
核心问题
- 网络环境不互通:
tft服务使用network_mode: host(直接使用宿主机网络),而postgres服务在自定义的network1网络中,两者不在同一网络域,无法直接通信。 - 连接地址错误:脚本中使用
127.0.0.1:5432,容器内的127.0.0.1指向容器自身,而非宿主机或PostgreSQL容器;同时PostgreSQL容器映射的宿主机端口是5433,和脚本中的5432不匹配。
推荐修复方案(统一自定义网络)
修改docker-compose.yml,让tft服务加入自定义网络,移除network_mode: host:
version: '3.4' networks: network1: name: my-network attachable: true ipam: driver: default config: - subnet: 172.18.0.0/16 ip_range: 172.18.5.0/24 gateway: 172.18.0.1 services: tft: image: tft build: context: . dockerfile: ./Dockerfile networks: - network1 # 加入自定义网络,和postgres处于同一网络 depends_on: - postgres # 确保postgres启动后再启动tft postgres: image: postgres:14.1-bullseye environment: POSTGRES_PASSWORD: "*********" POSTGRES_DB: your_db_name # 显式指定数据库名,和脚本参数一致 POSTGRES_USER: your_db_user # 显式指定用户名,和脚本参数一致 ports: - "5433:5432" networks: - network1
同时修改Python脚本的连接参数,将host设置为postgres(Docker Compose的服务名,会自动解析为容器IP),端口使用容器内部的5432:
# 调用示例 conn, cur = create_connection( host="postgres", dbname="your_db_name", user="your_db_user", password="*********" )
备选方案(保留host网络模式)
若必须使用network_mode: host,则修改postgres服务也使用host网络:
services: tft: image: tft build: context: . dockerfile: ./Dockerfile network_mode: host postgres: image: postgres:14.1-bullseye environment: POSTGRES_PASSWORD: "*********" network_mode: host # 和tft共享宿主机网络
此时脚本连接参数改为宿主机地址127.0.0.1,端口使用5432(host模式下PostgreSQL直接绑定宿主机5432端口):
conn, cur = create_connection( host="127.0.0.1", dbname="postgres", # 默认数据库名 user="postgres", # 默认用户名 password="*********" )
内容的提问来源于stack exchange,提问作者ichiu
相关产品推荐
相关产品推荐

