必须明确定义postgres和Python两个服务并配置共享网络,Python连接时host填服务名而非localhost,且需通过healthcheck(pg_isready)和服务依赖(condition: service_healthy)确保数据库就绪后再启动应用。

docker-compose.yml 文件里必须明确定义两个服务并配置网络互通,否则 Python 应用根本连不上 PostgreSQL。
PostgreSQL 服务要暴露正确端口且启用健康检查
只写 ports: - "5432:5432" 是开发机调试用的,容器间通信不能依赖宿主机端口。Python 服务连接 PostgreSQL 时,host 必须填服务名(如 postgres),而不是 localhost 或 127.0.0.1。
健康检查不是可选项,尤其在 Python 应用启动快于数据库就绪时:healthcheck 能让 Compose 等待 PostgreSQL 真正可连接后再启动下游服务。
- 务必使用
pg_isready而非curl或简单 TCP 检查,它能验证数据库进程和角色权限是否就绪 -
interval和timeout建议设为 5s,retries至少 10,避免因初始化慢导致启动失败 - 环境变量如
POSTGRES_USER、POSTGRES_PASSWORD、POSTGRES_DB缺一不可,Python 的连接字符串依赖它们
Python 服务需声明依赖并等待 PostgreSQL 就绪
Docker Compose 不保证启动顺序,depends_on 默认只检查容器是否运行,不等数据库就绪。必须配合 condition: service_healthy 才有效。
立即学习“Python免费学习笔记(深入)”;
- 在 Python 服务的
depends_on中显式写:postgres: { condition: service_healthy } - Python 应用自身也应具备重试逻辑,比如用
psycopg2.connect(..., connect_timeout=5)加 try/except 循环,避免启动瞬间报ConnectionRefusedError - 若用
alpine镜像,注意psycopg2-binary在 musl 环境下可能出问题,建议改用psycopg2+ 构建时安装postgresql-client和build-base
Django 或 FastAPI 连接字符串里的 host 必须是服务名
常见错误是把数据库 host 写成 localhost 或 127.0.0.1 —— 这会让 Python 容器去连自己内部的回环地址,而非 PostgreSQL 容器。
- Django 的
settings.py中 DATABASES 配置:'HOST': 'postgres'(与docker-compose.yml里 services 下的 service name 一致) - FastAPI 用
SQLALCHEMY_DATABASE_URL = "postgresql://devuser:devpass@postgres:5432/devdb",其中@postgres:5432是关键 - 不要映射 PostgreSQL 到宿主机非常规端口(如
"5433:5432")后又在 Python 里连localhost:5433,这破坏了容器网络隔离性,且无法用于 CI 或多环境部署
初始化 SQL 脚本必须放在 /docker-entrypoint-initdb.d/ 且权限正确
PostgreSQL 官方镜像只在 data 目录为空时执行该目录下的 .sql 或 .sh 文件。挂载方式错误或文件权限不对会导致静默跳过。
- 用
volumes挂载脚本时,路径必须是./init.sql:/docker-entrypoint-initdb.d/init.sql,不能漏掉/docker-entrypoint-initdb.d/前缀 - 确保
init.sql文件换行符为 LF(Linux 格式),Windows 编辑器保存时选 “UTF-8 无 BOM” - 如果已有数据卷,删掉再重建容器(
docker-compose down -v),否则 init 脚本不会再次运行
实际跑通的关键在于:PostgreSQL 容器必须先报告健康,Python 容器才启动;Python 连接时用的服务名必须和 Compose 里定义的一致;初始化脚本路径和触发时机必须匹配官方镜像行为。这三个点任一出错,都会表现为“连不上数据库”但日志里找不到明确报错。


















