使用docker compose启动FastAPI+PostgreSQL服务报连接被拒错误
根因说明
从你的运行日志可以直接定位核心问题:Docker Compose的depends_on配置仅保证PostgreSQL容器的启动顺序在API容器之前,不会等待PostgreSQL服务完成初始化、能够接受TCP连接。你贴的日志中API容器报错退出后,PostgreSQL才输出database system is ready to accept connections的就绪日志,完全符合这个问题的特征。
除此之外你还存在配置不匹配的问题,也需要同步修复。
解决步骤
1. 修复服务启动顺序问题
两种常用方案任选其一即可:
方案A:添加启动等待脚本
首先在项目根目录新建wait-for-db.sh文件,内容如下:#!/bin/sh set -e until PGPASSWORD=$DATABASE_PASSWORD psql -h "$DATABASE_HOST" -U "$DATABASE_USERNAME" -d "$DATABASE_NAME" -c '\q'; do >&2 echo "PostgreSQL 还未就绪,等待中..." sleep 1 done >&2 echo "PostgreSQL 已就绪,启动服务" exec "$@"修改Dockerfile,添加psql客户端依赖:
RUN apt-get update \ && apt-get -y install libpq-dev gcc postgresql-client \ && pip install psycopg2给脚本添加执行权限后,修改docker-compose.yaml中rest_api的启动命令:
rest_api: build: . command: sh -c "./wait-for-db.sh uvicorn app.main:app --host 0.0.0.0" # 其余原有配置保持不变方案B:用健康检查控制启动顺序
直接修改docker-compose.yaml,给db服务添加健康检查,同时调整rest_api的依赖逻辑:services: db: image: postgres:13-alpine # 原有配置保持不变 healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DATABASE_USERNAME} -d ${DATABASE_NAME}"] interval: 2s timeout: 2s retries: 10 rest_api: # 原有配置保持不变 depends_on: db: condition: service_healthy
2. 修复配置不一致问题
- 修正docker-compose.yaml中db服务的错误环境变量,你当前把
POSTGRES_USER的值设为了${DATABASE_TYPE}(一般这个变量值是postgresql,会导致数据库初始化的用户名不符合预期),修改后如下:db: environment: POSTGRES_USER: ${DATABASE_USERNAME} POSTGRES_PASSWORD: ${DATABASE_PASSWORD} POSTGRES_DB: ${DATABASE_NAME} - 取消database.py中从环境变量读取连接串代码的注释,不要硬编码连接信息,避免本地配置和容器配置不匹配:
确认你的.env文件中load_dotenv() db_type = os.getenv("DATABASE_TYPE") username = os.getenv("DATABASE_USERNAME") password = os.getenv("DATABASE_PASSWORD") host = os.getenv("DATABASE_HOST") port = os.getenv("DATABASE_PORT") name = os.getenv("DATABASE_NAME") SQLALCHEMY_DATABASE_URI = f"{db_type}://{username}:{password}@{host}:{port}/{name}"DATABASE_HOST配置为db,DATABASE_PORT配置为5432。
3. 检查Dockerfile路径配置
你提到Dockerfile位于./app目录下,但docker-compose里rest_api的build上下文默认是项目根目录,如果实际Dockerfile确实在app目录下,需要修改build配置:
rest_api: build: context: . dockerfile: ./app/Dockerfile # 其余原有配置保持不变
验证操作
修改完成后先清理旧的容器和数据卷,避免残留的旧PostgreSQL数据影响验证:
docker compose down -v docker compose up --build
内容的提问来源于stack exchange,提问作者Daniel Qiao
相关产品推荐
相关产品推荐

