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

Docker Compose依赖失效:首次启动web服务无法连接PostgreSQL

解决Docker Compose中Django服务首次启动因PostgreSQL未就绪导致迁移失败的问题

核心问题在于:depends_on 仅能保证 db 服务先于 web 服务启动,但无法确保PostgreSQL完成初始化(比如创建默认库、用户,完成内部启动流程)并处于可连接状态。首次启动时PostgreSQL初始化耗时较长,web 服务直接执行迁移就会因连接失败退出;第二次启动时PostgreSQL已完成初始化,能快速就绪,因此迁移正常执行。

以下是几种实用解决方案:

方案1:使用等待脚本前置检查

编写一个shell脚本,在执行迁移前轮询PostgreSQL的就绪状态,直到可连接后再继续执行后续命令。

  1. 创建 entrypoint.sh 脚本:
#!/bin/sh
# 等待PostgreSQL服务就绪
until pg_isready -h db -U postgres; do
  echo "等待PostgreSQL服务就绪..."
  sleep 2
done

# 执行数据库迁移
python manage.py migrate

# 启动Django服务
exec "$@"
  1. 给脚本添加执行权限:
chmod +x entrypoint.sh
  1. 修改Dockerfile,确保安装postgresql-client(提供pg_isready命令)并复制脚本:
FROM python:3.11-slim

# 安装PostgreSQL客户端
RUN apt-get update && apt-get install -y --no-install-recommends postgresql-client && rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 复制等待脚本
COPY entrypoint.sh .

COPY . .

ENTRYPOINT ["./entrypoint.sh"]
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
  1. 调整docker-compose.yml(无需修改depends_on,脚本已处理等待逻辑):
services:
  web:
    build: .
    depends_on:
      - db
    ports:
      - "8000:8000"
  db:
    image: postgres:latest
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: your_password
      POSTGRES_DB: your_db_name

方案2:配置Docker健康检查

给db服务添加健康检查,让web服务仅在db健康检查通过后才启动。

修改docker-compose.yml:

services:
  web:
    build: .
    command: sh -c "python manage.py migrate && python manage.py runserver 0.0.0.0:8000"
    depends_on:
      db:
        condition: service_healthy
    ports:
      - "8000:8000"
  db:
    image: postgres:latest
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: your_password
      POSTGRES_DB: your_db_name
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

service_healthy 条件会让web服务等待db的健康检查连续通过5次(每次间隔5秒)后再启动,确保PostgreSQL完全就绪。

方案3:迁移命令自动重试(快速测试用)

如果是开发环境,可直接在启动命令中加入重试逻辑,无需额外脚本或配置:

services:
  web:
    build: .
    command: sh -c "until python manage.py migrate; do echo '迁移失败,重试中...'; sleep 2; done && python manage.py runserver 0.0.0.0:8000"
    depends_on:
      - db
    ports:
      - "8000:8000"
  db:
    image: postgres:latest
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: your_password
      POSTGRES_DB: your_db_name

这个方法会循环执行迁移命令,直到成功为止,适合快速验证场景。

内容的提问来源于stack exchange,提问作者watch-this

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 05:55:30