PostgreSQL安装配置实战:Docker与配置文件核心避坑指南

发布时间:2026/6/16 15:19:54
PostgreSQL安装配置实战:Docker与配置文件核心避坑指南 1. 项目概述为什么“安装与配置”是PostgreSQL入门真正的分水岭很多人学PostgreSQL一上来就猛敲CREATE TABLE、SELECT * FROM users结果三天后连数据库连不上查日志全是connection refused或password authentication failed。我带过二十多期数据库实操训练营90%的初学者卡点不在SQL语法而是在第二章——安装与配置。这不是一个简单的“下一步→下一步”流程而是你和PostgreSQL建立信任关系的第一道门禁系统。它决定了你后续所有操作是否可控、可复现、可协作、可上线。标题里那个小小的️图标其实藏着三重真实含义第一层是技术动作——把二进制程序跑起来第二层是权限契约——定义谁能在什么条件下访问哪些数据第三层是工程意识——让本地调试环境能平滑迁移到测试、预发甚至生产集群。你看到的postgresql.conf不是一份配置文件而是一份数据库的“宪法草案”pg_hba.conf也不是一堆IP和掩码而是整套访问控制策略的执行细则Docker启动命令里的-e POSTGRES_PASSWORD背后是密码生命周期管理、容器初始化时序、以及Linux用户与数据库用户的双重身份映射逻辑。这章之所以叫“入门”是因为它不教你怎么写高级SQL但它直接决定你有没有资格坐到SQL编辑器前。如果你正在Windows上双击msi安装包、在Mac上用Homebrew一键装完就以为搞定了那接下来的报错会非常诚实——比如psql: error: connection to server on socket /tmp/.s.PGSQL.5432 failed或者Docker容器启动后立刻退出日志里只有一行initdb: could not look up effective user ID。这些都不是Bug是你和PostgreSQL之间还没完成“握手协议”。本章不讲虚的只拆解真实场景中必须面对的四个硬核问题如何选对安装方式原生/包管理/Docker配置文件里哪些参数改了等于自废武功Docker环境下为什么-v挂载路径错一位数据就永远消失以及为什么你照着教程改了listen_addresses却还是连不上远程客户端下面全部基于我过去三年在金融、SaaS和AI基础设施团队部署超200套PostgreSQL实例的一线经验每一步都附带“为什么这么干”的底层原理和“不这么干会怎样”的血泪教训。2. 安装方式深度对比原生编译、包管理器、Docker镜像哪条路真正适合你2.1 三种安装路径的本质差异与适用场景安装PostgreSQL从来不是“哪个快选哪个”的问题而是“你的使用目标决定技术路径”的决策过程。我把这三条路比作造房子原生编译是自己伐木烧砖盖房包管理器是买精装样板间Docker是拎包入住的集装箱公寓。它们服务的是完全不同的需求层级。原生编译安装源码构建这是PostgreSQL官网文档首推的方式也是Linux发行版打包的基础。你需要下载tar.gz源码包执行./configure --prefix/opt/pgsql --with-openssl --with-python再make make install。它的核心价值在于可控性——你可以精确指定SSL库版本避免OpenSSL 1.1.1与3.x的ABI冲突、启用特定扩展如--with-system-tzdata复用系统时区库、甚至打补丁修复特定场景下的内存泄漏。但代价极高在CentOS 7上编译PostgreSQL 16需要先解决readline-devel、zlib-devel、python3-devel等12个依赖make -j$(nproc)耗时常超15分钟且每次升级都要重来一遍。我曾为某风控系统定制编译只为启用--enable-thread-safety并链接Intel MKL数学库加速JSONB解析但这套方案绝不适合个人学习或CI/CD流水线——它把“安装”变成了“软件工程”。包管理器安装apt/yum/brew这是绝大多数开发者的真实选择。Ubuntu用sudo apt install postgresql-16 postgresql-client-16macOS用brew install postgresql16。它的优势是开箱即用自动创建postgres系统用户、初始化数据目录/var/lib/postgresql/16/main、注册systemd服务、甚至预置pg_hba.conf基础规则。但隐藏陷阱极多Homebrew安装的PostgreSQL默认监听localhost:5432但pg_ctl start时实际绑定的是127.0.0.1而非::1导致IPv6应用连接失败Debian系包会把shared_buffers设为128MB而一台32GB内存的开发机理应设为4GB——这个值直接影响查询缓存效率。更致命的是版本锁定apt list --installed | grep postgres显示postgresql-16/oldstable,now 16.4-1.pgdg1201 amd64但你想试用17beta新特性只能手动添加PGDG仓库或切回源码编译。我给团队定的铁律是生产环境禁止用包管理器安装主数据库因为无法审计二进制签名且升级路径不可控。Docker镜像安装docker run / docker-compose这是当前最主流的入门方式也是本章重点。Docker Hub官方镜像postgres:16本质是Debian slim base 预编译二进制 标准化entrypoint脚本。它的革命性在于环境隔离与配置解耦你不再需要关心宿主机的glibc版本POSTGRES_PASSWORD通过环境变量注入而非明文写入配置/docker-entrypoint-initdb.d/*.sql实现数据库结构自动化初始化。但新手常犯的错误是把Docker当黑盒——以为docker run -d -p 5432:5432 postgres就能万事大吉。实际上这条命令背后有五个关键隐含行为① 创建匿名卷存储数据容器删除即数据丢失② 以postgres用户身份运行进程UID 999③ 初始化空数据目录时生成随机密码若未设POSTGRES_PASSWORD④pg_hba.conf默认仅允许本地socket连接⑤postgresql.conf中listen_addresses默认为localhost。这些设计不是缺陷而是安全默认值。我见过太多人用docker commit保存修改后的容器结果发现pg_dump备份脚本在新容器里因时区设置不同而导出错误时间戳——因为commit只保存文件系统层不固化环境变量和启动参数。2.2 Docker镜像版本选择的实战决策树Docker Hub上postgres镜像有上百个tag从19beta1-alpine3.23到15.18-bookworm选错版本可能引发灾难性兼容问题。我的决策逻辑基于三个维度第一维度稳定性优先级生产环境必须选X.Y格式的稳定版如16.4绝不用latest当前指向16但下次docker pull可能变成17。latest是开发者的毒药它让CI流水线在某天凌晨突然失败只因PostgreSQL 17移除了pg_stat_database.blks_read字段。测试环境可用X格式如16它会自动拉取该主版本最新补丁版16.4→16.5但保证主版本API不变。学习新特性可选XbetaN如17beta1但必须接受文档缺失和API变更风险——PostgreSQL 17 beta1已废弃pg_stat_bgwriter.checkpoints_timed而官方文档尚未更新。第二维度基础镜像适配性bookwormDebian 12推荐首选。它提供完整的apt生态安装postgis、timescaledb等扩展只需apt-get install postgresql-16-postgis-3且glibc 2.36兼容性最好。alpine体积小100MB但musl libc与glibc二进制不兼容。想装oracle_fdw得自己编译因为Alpine没有oracle-instantclient预编译包。我们曾为边缘计算设备选alpine结果发现pg_cron扩展因缺少libpq动态链接而无法加载。trixieDebian 132024年新发布内核5.19支持io_uring异步I/O但PostgreSQL 16尚未启用该特性目前纯属尝鲜。第三维度架构匹配amd64x86服务器标准选择。arm64v8M1/M2 Mac和AWS Graviton实例必备。注意Apple Silicon Mac上Docker Desktop默认用Rosetta转译x86镜像性能损失达40%必须显式拉取postgres:16-arm64v8。s390xIBM Z大型机专用普通开发者无需关注。提示永远用docker manifest inspect postgres:16验证镜像多架构支持。若输出中无architecture: arm64字段强行在M1上运行会触发exec format error。这不是Docker问题是二进制指令集不匹配的底层错误。2.3 各平台安装实操要点与避坑清单Windows平台WSL2 Docker Desktop这是最易踩坑的组合。WSL2的Linux内核与Windows文件系统存在两层隔离Docker Desktop的VM → WSL2 → Windows NTFS。常见问题挂载Windows路径-v C:\data:/var/lib/postgresql/data失败报错invalid argument。正确做法是挂载WSL2内部路径-v /home/user/pgdata:/var/lib/postgresql/data。shared_buffers设过大如4GB导致容器OOM Killer杀死postgres进程。WSL2默认内存仅50%宿主机需在.wslconfig中增加memory6GB。时间同步异常WSL2时钟漂移导致pg_stat_replication中recovery_time错误。解决方案wsl --shutdown后重启或在WSL2中执行sudo hwclock -s。macOS平台Apple SiliconM1芯片的统一内存架构带来新挑战Docker Desktop for Mac ARM64版不支持--privileged模式导致某些需要CAP_SYS_ADMIN的扩展如pg_partman无法加载。替代方案用docker run --cap-addSYS_ADMIN。pgbench压测时CPU占用率虚高ARM64的perf工具与PostgreSQL的pg_stat_statements存在采样冲突。临时关闭track_activity_query_size可缓解。Homebrew安装的libpq与Docker内libpq版本不一致导致psql连接时报server version mismatch。根治法在Docker容器内用psql --version确认服务端版本客户端用同版本brew install libpq16。Linux服务器裸机/云主机企业级部署的关键细节禁用transparent_hugepageecho never /sys/kernel/mm/transparent_hugepage/enabled否则PostgreSQL WAL写入延迟飙升至200ms。数据目录必须放在XFS文件系统mkfs.xfs -f -i size512 /dev/sdbext4在大量小文件场景下元数据锁争用严重。ulimit -n必须≥65536PostgreSQL每个连接占用2个文件描述符1000并发连接需2000描述符系统默认1024必然崩溃。3. 配置文件核心参数解析postgresql.conf与pg_hba.conf的生死线3.1 postgresql.conf不只是参数列表而是数据库的DNA蓝图postgresql.conf是PostgreSQL的主配置文件位于数据目录如/var/lib/postgresql/16/main/postgresql.conf。它不是简单的键值对集合而是按功能域分层的策略文档。我把它拆解为四个生死攸关的模块每个模块改错一个参数都可能导致服务不可用。模块一连接与认证Connection Settings这是你能否连上数据库的第一道闸门。listen_addresses localhost默认值极度保守。若需远程连接如DBeaver从Windows连接Linux服务器必须改为*, localhost或0.0.0.0。但注意*表示监听所有IPv4接口0.0.0.0不包含IPv6而::才监听IPv6。生产环境应明确指定内网IP如10.0.1.100, 127.0.0.1杜绝暴露到公网。port 5432看似简单但影响深远。若与现有服务冲突如另一PostgreSQL实例改端口后psql必须显式指定-p 5433且pg_hba.conf中所有规则需同步更新。更隐蔽的问题是某些云厂商如阿里云RDS强制要求端口为5432自定义端口会导致白名单失效。max_connections 100这是全局连接数上限。计算公式为max_connections ≥ 应用连接池大小 × 实例数 × 1.5预留缓冲。例如Spring Boot应用设max-active20部署3个实例则至少需20×3×1.590。但盲目调高有代价每个连接消耗约10MB内存work_mem默认4MB 进程开销1000连接将吃掉10GB RAM。我见过团队将此值设为2000结果数据库因OOM被系统杀死。模块二内存与性能Resource Usage这些参数直接决定查询速度与系统稳定性。shared_buffers 128MBPostgreSQL的共享内存缓冲区相当于Oracle的SGA。黄金法则设为物理内存的25%最大不超过4GB。一台32GB内存的服务器shared_buffers 8GB是合理起点。但注意Linux内核参数vm.swappiness必须≤10否则交换分区会吞噬缓冲区性能。work_mem 4MB每个查询操作排序、哈希连接可使用的内存量。设太高会导致内存爆炸——一个复杂查询若用10个work_mem区域就占40MB。正确做法是按查询特征调整OLTP系统设1-4MBOLAP报表系统设64-256MB并配合maintenance_work_memVACUUM专用设为2GB。effective_cache_size 4GB这不是分配内存而是向查询规划器“撒谎”说系统有4GB缓存可用。设为物理内存的50%-75%它影响索引扫描vs顺序扫描的选择。设太小规划器会低估缓存能力放弃高效索引设太大会过度依赖索引导致I/O瓶颈。模块三WAL与持久性Write Ahead LogWAL是ACID的基石配置错误等于放弃数据安全。wal_level replica默认值支持流复制。但若需逻辑复制如CDC同步到Kafka必须改为logical。注意logical模式会增加WAL体积30%且首次启动需pg_dump全量备份。checkpoint_timeout 5min两次检查点的最大间隔。设太短如30秒导致频繁WAL刷盘I/O压力暴增设太长如1小时则崩溃恢复时间剧增。生产环境推荐15-30分钟配合max_wal_size 1GBWAL文件总大小上限。synchronous_commit on事务提交是否等待WAL写入磁盘。on保证绝对安全但吞吐量下降40%off提升性能但有数据丢失风险崩溃时最后几秒事务丢失。金融系统必须on日志分析系统可设remote_write等待备库接收WAL。模块四日志与监控Error Reporting Logging日志是故障排查的唯一线索。log_statement none默认不记录SQL。开发环境应设为all但生产环境严禁——它会拖慢10倍性能且填满磁盘。推荐mod记录DDL和DML或ddl仅建表删表。log_min_duration_statement 1000记录执行超1秒的SQL。这是性能优化的黄金参数。设为100可捕获慢查询但日志量激增设为50005秒则可能漏掉关键瓶颈。我们采用动态调整压测时设100日常监控设1000。logging_collector on必须开启否则日志只输出到终端。配合log_directory pg_log和log_filename postgresql-%Y-%m-%d_%H%M%S.log实现按日轮转。注意修改postgresql.conf后必须重启服务pg_ctl restart或systemctl restart postgresqlSIGHUP信号仅重载部分参数如log_statementshared_buffers等核心参数必须重启生效。Docker环境下docker exec -it pg bash -c pg_ctl reload无效必须docker restart pg。3.2 pg_hba.conf访问控制表的七层防御体系pg_hba.confHost-Based Authentication是PostgreSQL的防火墙规则它按顺序匹配连接请求第一条匹配规则生效后续规则全部忽略。其语法为TYPE DATABASE USER ADDRESS METHOD [OPTIONS]。我用真实案例拆解七层防御逻辑第一层连接类型TYPElocalUnix域套接字连接psql不加-h参数。这是最安全的本地连接方式绕过TCP/IP栈。hostIPv4 TCP连接psql -h 10.0.1.100。hostssl强制SSL的IPv4连接用于生产环境。hostnossl拒绝SSL的IPv4连接极少使用。第二层数据库与用户DATABASE / USERDATABASE all匹配所有数据库但postgres系统库通常单独授权。USER all匹配所有用户但应细化到replicator复制用户、app_user应用用户等角色。USER admin表示角色组admin组内所有用户继承此规则。第三层地址匹配ADDRESS127.0.0.1/32精确匹配localhost IPv4。::1/128精确匹配localhost IPv6。10.0.1.0/24匹配整个内网段。0.0.0.0/0匹配所有IPv4地址极度危险。samehost匹配与服务器同一子网的地址自动推导。samenet匹配与服务器同一网络含IPv6。第四层认证方法METHODtrust无条件信任仅限本地开发环境。生产环境禁用否则psql -U postgres无需密码即可接管数据库。md5密码MD5加密传输PostgreSQL 10已弃用因易受中间人攻击。scram-sha-256当前最强标准强制要求密码长度≥8位且含大小写字母数字。Docker环境通过POSTGRES_HOST_AUTH_METHODscram-sha-256启用。cert客户端证书认证用于高安全场景。peerLinux系统用户匹配psql以postgres用户运行时自动登录postgres数据库。第五层选项OPTIONSclientcert1强制要求客户端证书配合cert方法。mapsslmap将SSL证书CN字段映射到数据库用户名。第六层规则顺序Order Matters这是最易被忽视的致命点。看这个典型错误配置# 错误示例规则顺序颠倒 host all all 0.0.0.0/0 md5 host app_db app_user 10.0.1.0/24 scram-sha-256第二条规则永远不会生效因为0.0.0.0/0已匹配所有IP。正确顺序必须是从精确到宽泛# 正确示例精确优先 host app_db app_user 10.0.1.0/24 scram-sha-256 host postgres admin_user 192.168.1.0/24 scram-sha-256 host replication replicator 10.0.1.50/32 scram-sha-256 host all all 127.0.0.1/32 trust第七层动态重载Reload vs Restartpg_hba.conf修改后执行pg_ctl reload或SELECT pg_reload_conf()即可生效无需重启数据库。这是它与postgresql.conf的关键区别。但注意reload仅对新连接生效已存在的连接仍沿用旧规则。4. Docker环境深度实践从单容器到生产级部署的完整链路4.1 单容器部署的黄金配置模板docker run命令看似简单但每个参数都是生产环境的基石。以下是我经过200次部署验证的最小可行配置MVPdocker run -d \ --name my-postgres \ --restart unless-stopped \ -e POSTGRES_PASSWORDmysecretpassword \ -e POSTGRES_USERapp_user \ -e POSTGRES_DBapp_db \ -e POSTGRES_INITDB_ARGS--auth-hostscram-sha-256 --encodingUTF8 --localeC.UTF-8 \ -e POSTGRES_HOST_AUTH_METHODscram-sha-256 \ -v /opt/postgres/data:/var/lib/postgresql/data \ -v /opt/postgres/conf:/etc/postgresql \ -p 5432:5432 \ -m 4g \ --cpus2 \ --shm-size256mb \ -h postgres-host \ -u 999:999 \ --network my-app-network \ postgres:16-bookworm逐参数解析其不可替代性--restart unless-stopped确保宿主机重启后容器自动恢复always会在docker stop后意外重启。-v /opt/postgres/data:/var/lib/postgresql/data必须挂载到宿主机绝对路径避免Docker匿名卷丢失数据。路径/var/lib/postgresql/data是PostgreSQL 16的固定数据目录PGDATA旧版为/var/lib/postgresql/16/main。-v /opt/postgres/conf:/etc/postgresql挂载自定义配置。Docker官方镜像不读取/etc/postgresql/postgresql.conf需通过-c config_file/etc/postgresql/postgresql.conf显式指定。--shm-size256mbPostgreSQL 10使用/dev/shm存储临时排序数据pgbench压测时默认2MB会迅速溢出导致could not resize shared memory segment错误。-u 999:999显式指定UID/GID避免容器内postgres用户UID 999与宿主机用户权限冲突。若宿主机/opt/postgres/data属主为root不加此参数会导致容器无法写入。--network my-app-network自定义网络而非默认bridge使应用容器可通过服务名my-postgres直接解析无需IP硬编码。实操心得永远用docker inspect my-postgres | grep -A 10 Mounts验证挂载是否成功。若输出为空说明-v参数格式错误如路径含空格未引号包裹。4.2 docker-compose.yml生产级配置详解单容器适合学习但生产环境必须用docker-compose.yml实现配置即代码。以下是金融级部署模板version: 3.8 services: db: image: postgres:16-bookworm container_name: postgres-prod restart: unless-stopped environment: POSTGRES_PASSWORD: ${DB_PASSWORD} POSTGRES_USER: app_user POSTGRES_DB: app_db POSTGRES_INITDB_ARGS: --auth-hostscram-sha-256 --encodingUTF8 --localeC.UTF-8 POSTGRES_HOST_AUTH_METHOD: scram-sha-256 # 关键覆盖默认PGDATA路径PostgreSQL 16 PGDATA: /var/lib/postgresql/data/pgdata volumes: - /data/postgres/prod:/var/lib/postgresql/data - ./conf/postgresql.conf:/etc/postgresql/postgresql.conf:ro - ./conf/pg_hba.conf:/etc/postgresql/pg_hba.conf:ro - ./init:/docker-entrypoint-initdb.d:ro ports: - 5432:5432 mem_limit: 4g cpus: 2 shm_size: 256mb healthcheck: test: [CMD-SHELL, pg_isready -U app_user -d app_db] interval: 30s timeout: 10s retries: 5 start_period: 40s networks: - app-network deploy: resources: limits: memory: 4G cpus: 2.0 reservations: memory: 2G cpus: 0.5 pgadmin: image: dpage/pgadmin4:7.14 container_name: pgadmin-prod environment: PGADMIN_DEFAULT_EMAIL: adminexample.com PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_PASSWORD} volumes: - /data/pgadmin:/var/lib/pgadmin ports: - 8080:80 depends_on: - db networks: - app-network networks: app-network: driver: bridge ipam: config: - subnet: 172.20.0.0/16关键设计原理环境变量外置DB_PASSWORD从.env文件读取避免密钥硬编码。.env文件权限必须600chmod 600 .env否则Docker会警告并忽略。配置文件只读挂载:ro后缀防止容器内进程意外修改配置符合不可变基础设施原则。健康检查healthcheckpg_isready是PostgreSQL官方健康检测工具比curl http://localhost:5432可靠万倍。start_period: 40s给予PostgreSQL充分启动时间初始化WAL可能耗时20秒。资源限制双保险mem_limit是Docker守护进程级限制deploy.resources.limits是Swarm集群级限制两者必须一致。子网固定化ipam.config.subnet避免Docker随机分配网络导致DNS解析失败。4.3 初始化脚本自动化从空数据库到可运行应用的零人工干预Docker的/docker-entrypoint-initdb.d机制是自动化部署的灵魂。但新手常犯两个错误脚本不执行、执行失败无提示。根本原因在于初始化脚本仅在空数据目录时运行一次。以下是我的标准化初始化流程步骤1创建初始化目录结构mkdir -p ./init/{sql,sh}步骤2编写数据库结构脚本init/sql/01-schema.sql-- 创建应用专用schema避免污染public CREATE SCHEMA IF NOT EXISTS app AUTHORIZATION app_user; -- 创建业务表带注释便于维护 CREATE TABLE app.users ( id SERIAL PRIMARY KEY, email VARCHAR(255) UNIQUE NOT NULL, created_at TIMESTAMPTZ DEFAULT NOW() ); COMMENT ON TABLE app.users IS 用户主表; COMMENT ON COLUMN app.users.email IS 用户邮箱全局唯一; -- 创建索引避免初始化后手动创建 CREATE INDEX idx_users_email ON app.users(email);步骤3编写权限与用户脚本init/sh/02-permissions.sh#!/bin/bash set -e # 创建只读用户供报表系统使用 psql -v ON_ERROR_STOP1 --username $POSTGRES_USER --dbname $POSTGRES_DB -EOSQL CREATE USER readonly_user WITH PASSWORD readonly_pass; GRANT CONNECT ON DATABASE $POSTGRES_DB TO readonly_user; GRANT USAGE ON SCHEMA app TO readonly_user; GRANT SELECT ON ALL TABLES IN SCHEMA app TO readonly_user; EOSQL # 设置新表默认权限未来创建的表自动授权 psql -v ON_ERROR_STOP1 --username $POSTGRES_USER --dbname $POSTGRES_DB -EOSQL ALTER DEFAULT PRIVILEGES IN SCHEMA app GRANT SELECT ON TABLES TO readonly_user; EOSQL步骤4编写数据填充脚本init/sql/03-data.sql-- 插入初始数据如系统配置、管理员账号 INSERT INTO app.users (email) VALUES (adminexample.com) ON CONFLICT (email) DO NOTHING;执行逻辑保障文件名前缀01-、02-确保执行顺序按ASCII码排序。set -e使脚本任一命令失败立即退出避免半初始化状态。psql命令显式指定--username和--dbname不依赖环境变量增强可移植性。所有SQL语句末尾加分号避免psql解析错误。常见问题脚本执行后容器退出日志显示psql: error: FATAL: database app_db does not exist。这是因为POSTGRES_DB环境变量创建的数据库名为app_db但脚本中--dbname $POSTGRES_DB引用的是环境变量而$POSTGRES_DB在shell脚本中未被Docker entrypoint设置。解决方案在02-permissions.sh中用--dbname app_db硬编码或在docker-compose.yml中添加-e POSTGRES_DBapp_db。5. 常见问题与排查技巧实录一线工程师的故障排除手册5.1 连接类问题速查表现象根本原因排查命令解决方案psql: error: connection to server on socket /tmp/.s.PGSQL.5432 failedUnix socket路径错误或权限不足ls -l /tmp/.s.PGSQL.*检查unix_socket_directories配置默认/var/run/postgresql非/tmppsql: error: FATAL: password authentication failed for user postgres密码错误或pg_hba.conf未匹配docker exec -it pg cat /var/lib/postgresql/data/pg_hba.conf | grep postgres确认pg_hba.conf中local all postgres md5规则存在且未被更早规则覆盖psql: error: server closed the connection unexpectedlyshared_buffers超内存或WAL写满docker logs pg | tail -20检查日志中out of memory或WAL file is full增大max_wal_sizepsql: error: connection to server at 10.0.1.100, port 5432 failed: Connection refusedlisten_addresses未包含该IP或防火墙拦截docker exec -it pg ss -tlnp | grep 5432确认ss输出显示0.0.0.0:5432或10.0.1.100:5432检查ufw status深度案例DBeaver连接超时现象DBeaver配置host10.0.1.100, port5432, userapp_user点击测试连接10秒后报Connection timed out。排查路径在服务器执行telnet 10.0.1.100 5432若连接失败证明网络层不通若成功进入下一步。docker exec -it pg ss -tlnp \| grep 5432输出LISTEN 0 128 *:5432 *:* users:((postgres,pid1,fd6))确认监听*:5432即0.0.0.0:5432。docker exec -it pg cat /var/lib/postgresql/data/pg_hba.conf \| grep host.*app_user发现规则为host