You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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文件。

解决步骤

  1. 验证环境变量读取情况
    在db.py开头添加调试代码,输出实际读取到的配置值:
# 添加到db.py顶部
print("DB_HOST:", config('DB_HOST'))
print("DATABASE_URL:", DATABASE_URL)

启动容器后查看web服务日志,确认是否读取到db而非localhost。

  1. 恢复正确的DB_HOST配置
    将.env中的DB_HOST改回db,无需给db服务添加端口映射(容器内部通信不需要映射到宿主机)。

  2. 处理数据库启动就绪延迟
    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/*
  1. 检查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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 18:15:36