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

Docker容器无法互连:Django-Rest与PostgreSQL连接失败排查

问题分析与解决方案

问题原因

Docker Compose 中的 depends_on 仅能确保 db 容器在 backend 容器之前启动,但无法保证 PostgreSQL 服务已经完成初始化并处于就绪状态。PostgreSQL 启动时需要完成数据库创建、用户权限配置等操作,这个过程需要几秒时间;而 backend 容器启动后会立即尝试连接数据库,此时 Postgres 尚未准备好,就会抛出连接拒绝错误。

解决方案

方案1:为后端容器添加启动等待脚本

在 Django 容器的启动流程中加入等待 Postgres 就绪的逻辑,确认数据库可连接后再启动 Django 服务。

方法A:自定义检查脚本

在你的 Django 项目目录(./api 下)创建一个 wait-for-postgres.sh 脚本:

#!/bin/bash
set -e

host="$1"
port="$2"
shift 2
cmd="$@"

until pg_isready -h "$host" -p "$port"; do
  >&2 echo "Postgres 未就绪 - 等待1秒"
  sleep 1
done

>&2 echo "Postgres 已就绪 - 启动服务"
exec $cmd

给脚本添加执行权限:

chmod +x wait-for-postgres.sh

修改 ./api/Dockerfile 的启动命令:

CMD ["./wait-for-postgres.sh", "db", "5432", "--", "python", "manage.py", "runserver", "0.0.0.0:8000"]

注意:需确保 Django 容器中安装了 postgresql-client,可在 Dockerfile 中添加:RUN apt-get update && apt-get install -y postgresql-client

方法B:直接在启动命令中写循环检查

如果不想额外添加脚本,可直接修改 Dockerfile 的启动命令:

CMD sh -c "until pg_isready -h db -p 5432; do sleep 1; done; python manage.py runserver 0.0.0.0:8000"

方案2:利用 Docker Compose 健康检查

通过给 db 服务添加健康检查,让 backend 容器等待 db 服务进入健康状态后再启动。

修改 docker-compose.yml:

version: '3.9'
services:
  
  db:
    image: postgres:latest
    restart: always
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=85842475DB
      - POSTGRES_DB=sports_center_db
      - POSTGRES_PORT=5432
    # 添加健康检查配置
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres -d sports_center_db"]
      interval: 5s
      timeout: 5s
      retries: 5
  
  backend:
    build: ./api
    depends_on:
      # 等待db服务进入健康状态
      db:
        condition: service_healthy
    ports:
      - "8000:8000"
    environment:
      - DB_NAME=sports_center_db
      - DB_USER_NAME=postgres
      - DB_PASSWORD=85842475DB
      - DB_HOST=db
      - DB_PORT=5432

方案3:让 Django 自动重试数据库连接

修改 manage.py,在启动服务前添加数据库连接重试逻辑:

import time
import sys
from django.db import connections
from django.db.utils import OperationalError

def wait_for_db():
    while True:
        try:
            db_conn = connections['default']
            db_conn.ensure_connection()
            break
        except OperationalError:
            print('数据库未就绪,等待1秒...')
            time.sleep(1)

if __name__ == "__main__":
    wait_for_db()
    from django.core.management import execute_from_command_line
    execute_from_command_line(sys.argv)

这样启动 Django 时会自动循环尝试连接数据库,直到成功再执行后续命令。


内容的提问来源于stack exchange,提问作者Abdur Rahman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 04:50:26