Docker中PostgreSQL未监听指定端口5433的连接问题排查
问题描述
我无法连接Docker中运行的PostgreSQL,容器并未监听指定的5433端口,而是使用了默认的5432端口(本地已有非Docker的PostgreSQL占用该端口)。通过Docker Python模块部署测试镜像/容器时表面无异常,但install.py连接数据库时出现以下错误:
psycopg2.OperationalError: server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
Docker日志显示容器启动后停止再重启,但始终监听5432端口。
日志内容:
waiting for server to shut down...2023-09-03 16:59:24.181 UTC [47] LOG: received fast shutdown request .2023-09-03 16:59:24.181 UTC [47] LOG: aborting any active transactions 2023-09-03 16:59:24.182 UTC [47] LOG: background worker "logical replication launcher" (PID 53) exited with exit code 1 2023-09-03 16:59:24.183 UTC [48] LOG: shutting down 2023-09-03 16:59:24.184 UTC [48] LOG: checkpoint starting: shutdown immediate 2023-09-03 16:59:24.269 UTC [48] LOG: checkpoint complete: wrote 4473 buffers (27.3%); 0 WAL file(s) added, 0 removed, 2 recycled; write=0.023 s, sync=0.060 s, total=0.086 s; sync files=963, longest=0.001 s, average=0.001 s; distance=34921 kB, estimate=34921 kB 2023-09-03 16:59:24.285 UTC [47] LOG: database system is shut down done server stopped PostgreSQL init process complete; ready for start up. 2023-09-03 16:59:24.415 UTC [1] LOG: starting PostgreSQL 15.4 (Debian 15.4-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit 2023-09-03 16:59:24.415 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432 2023-09-03 16:59:24.415 UTC [1] LOG: listening on IPv6 address "::", port 5432 2023-09-03 16:59:24.416 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432" 2023-09-03 16:59:24.419 UTC [71] LOG: database system was shut down at 2023-09-03 16:59:24 UTC 2023-09-03 16:59:24.423 UTC [1] LOG: database system is ready to accept connections
Dockerfile内容:
FROM postgres:12.15 FROM postgis/postgis ENV POSTGRES_USER awdn ENV POSTGRES_PASSWORD **** ENV POSTGRES_DB awdn_data ENV POSTGRES_PORT 5433 EXPOSE 5433
install.py内容:
import docker,psycopg2 client = docker.from_env() client.containers.prune() try: container = client.containers.get('dbase') container.stop() container.remove() except docker.errors.NotFound as e: print("The container is not running.\n") try: awdnunittest = client.images.get('awdn-unit-test') client.images.remove(awdnunittest.short_id) except docker.errors.NotFound as e: print("No image exists for the unittest.\nThe psql image is being installed...\n") client.images.build(path='./',tag='awdn-unit-test') client.containers.run('awdn-unit-test',name='dbase',ports={'5433':5433},detach=True,publish_all_ports=True) conn = psycopg2.connect("dbname=awdn_data user=awdn port=5433 password=**** host=localhost")
解决方案
1. 修复Dockerfile基础镜像与端口配置问题
- 你的Dockerfile使用了两次
FROM指令,这会导致仅最后一个FROM postgis/postgis生效,之前的postgres:12.15被完全忽略,导致实际运行的PostgreSQL版本与预期不符。 - PostgreSQL官方镜像不识别
POSTGRES_PORT环境变量,需使用PGPORT指定监听端口。
修改后的Dockerfile:
FROM postgis/postgis:12-3.3 # 选用对应PostgreSQL 12版本的PostGIS镜像,保持版本一致性 ENV POSTGRES_USER awdn ENV POSTGRES_PASSWORD **** ENV POSTGRES_DB awdn_data ENV PGPORT 5433 # 替换POSTGRES_PORT为PGPORT EXPOSE 5433
2. 修正容器端口映射逻辑
若容器内PostgreSQL已通过PGPORT改为监听5433,端口映射保持{'5433':5433}即可;若未修改容器内端口,需将容器内默认的5432端口映射到宿主机5433,即{'5432':5433}。
3. 添加容器启动等待逻辑
install.py中启动容器后立刻执行数据库连接,此时容器内PostgreSQL可能尚未完全初始化完成,需添加等待逻辑:
import time # ... 启动容器的代码 ... container = client.containers.run('awdn-unit-test',name='dbase',ports={'5433':5433},detach=True,publish_all_ports=True) # 等待PostgreSQL服务就绪 while True: logs = container.logs().decode('utf-8') if "database system is ready to accept connections" in logs: break time.sleep(1) # 执行连接操作 conn = psycopg2.connect("dbname=awdn_data user=awdn port=5433 password=**** host=localhost")
4. 验证容器端口监听状态
启动容器后,执行以下命令检查容器内端口监听情况,确认PostgreSQL是否监听在指定端口:
docker exec -it dbase netstat -tulpn
内容的提问来源于stack exchange,提问作者deadpickle
相关产品推荐
相关产品推荐

