Docker容器内PostgreSQL数据库连接失败问题求助
Docker容器部署PostgreSQL连接失败问题排查求助
相关配置文件
docker-compose.yaml
version: '3.9' services: web: env_file: .env build: . command: sh -c "alembic upgrade head && uvicorn main:app --host 0.0.0.0 --port 8000" volumes: - .:/app ports: - 8000:8000 depends_on: - db - redis db: image: postgres:11 volumes: - postgres_data:/var/lib/postgresql/data environment: - POSTGRES_USER=${DB_USER} - POSTGRES_PASSWORD=${DB_PASS} - POSTGRES_DB=${DB_NAME} redis: image: redis:6-alpine volumes: postgres_data:
.env
DB_USER='wplay' DB_PASS='wplay' DB_HOST=db DB_NAME='wplay' DB_PORT=5432
报错信息
启动容器后web服务输出错误:
web_1 | could not connect to server: Cannot assign requested address web_1 | Is the server running on host "localhost" (::1) and accepting web_1 | TCP/IP connections on port 5432?
已尝试操作
- 修改
.env中的DB_HOST='localhost' - 在
docker-compose.yaml的db服务中添加端口映射:ports: - '5432:5432'
问题仍未解决。
更新信息
db服务日志
db_1 | db_1 | PostgreSQL Database directory appears to contain a database; Skipping initialization db_1 | db_1 | 2023-01-04 12:44:55.386 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432 db_1 | 2023-01-04 12:44:55.386 UTC [1] LOG: listening on IPv6 address "::", port 5432
数据库连接代码(db.py)
import os from decouple import config import databases import sqlalchemy DEFAULT_DATABASE_URL = f"postgresql://{config('DB_USER')}:{config('DB_PASS')}" \ f"@{config('DB_HOST')}:5432/{config('DB_NAME')}" DATABASE_URL = (os.getenv('DATABASE_URL', DEFAULT_DATABASE_URL)) database = databases.Database(DATABASE_URL) metadata = sqlalchemy.MetaData() engine = sqlalchemy.create_engine(DATABASE_URL) metadata.create_all(engine)
排查与解决方案
核心问题分析
报错显示web服务仍在尝试连接localhost,但.env中配置的DB_HOST=db(docker-compose服务名,容器间应能正常解析),说明环境变量未被正确加载,或代码中config方法读取的不是目标.env文件。
解决步骤
- 验证环境变量读取情况
在db.py开头添加调试代码,输出实际读取到的配置值:
# 添加到db.py顶部 print("DB_HOST:", config('DB_HOST')) print("DATABASE_URL:", DATABASE_URL)
启动容器后查看web服务日志,确认是否读取到db而非localhost。
恢复正确的DB_HOST配置
将.env中的DB_HOST改回db,无需给db服务添加端口映射(容器内部通信不需要映射到宿主机)。处理数据库启动就绪延迟
depends_on仅保证db服务启动顺序,不保证PostgreSQL服务完全就绪。修改web服务的启动命令,添加等待逻辑:
# docker-compose.yaml中web的command替换为 command: sh -c "until pg_isready -h db -p 5432 -U ${DB_USER}; do sleep 1; done && alembic upgrade head && uvicorn main:app --host 0.0.0.0 --port 8000"
注意:需确保web镜像中安装了postgresql-client,可在Dockerfile中添加:
RUN apt-get update && apt-get install -y postgresql-client && rm -rf /var/lib/apt/lists/*
- 检查DATABASE_URL覆盖问题
代码优先使用os.getenv('DATABASE_URL'),若该变量在Dockerfile或其他配置中被设置,会覆盖拼接的DEFAULT_DATABASE_URL,需确认该变量未被意外赋值。
验证方法
启动容器后,进入web容器测试数据库连接:
docker exec -it <web容器名称> psql -h db -U wplay -d wplay
若能成功连接,说明容器间网络正常,问题出在代码的环境变量读取环节。
内容的提问来源于stack exchange,提问作者Jekson
相关产品推荐
相关产品推荐

