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

Docker部署Django+Celery遇迁移错误求助:UniqueViolation等问题

问题拆解与解决方案

我来帮你梳理下你遇到的这几个问题——Django健康检查失败、Celery/Celery-beat的数据库迁移冲突,这类容器化Django+Celery架构的问题其实挺常见的,咱们一步步来解决:

一、先搞定Django健康检查失败的问题

你现在用curl http://0.0.0.0:8000做健康检查,大概率是两个原因:要么Django容器里没装curl,要么你的Django服务根本没在这个地址正常响应(比如DEBUG关闭后默认首页没启用)。给你两个更可靠的方案:

  • 方案1:改用Django自带的检查命令(不需要额外装依赖)
    修改docker-compose里web服务的healthcheck:

    healthcheck:
      test: ["CMD", "python", "manage.py", "check", "--deploy"]
      interval: 30s
      timeout: 10s
      retries: 5
    

    manage.py check --deploy会检查Django的生产环境配置是否正确,能准确反映服务是否就绪。

  • 方案2:给容器装curl(如果坚持用HTTP检查)
    在你的Django Dockerfile里加一行:

    RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/*
    

    同时确保你的Django启动命令是python manage.py runserver 0.0.0.0:8000,保证服务监听所有接口。

二、解决Celery/Celery-beat的数据库迁移冲突

你遇到的UniqueViolation(序列重复)和DuplicateTable(django_migrations重复)错误,核心原因是多个服务同时执行了数据库迁移操作,或者迁移后数据库序列没同步。

核心问题拆解:

  1. 哪怕你配置了depends_on: service_healthy,如果Celery/Celery-beat的启动脚本里也写了migrate,就会和web容器的migrate撞车,导致重复创建表或序列。
  2. 你删除数据库重建后,PostgreSQL的序列(比如auth_permission_id_seq)可能没完全重置,或者多个进程同时操作序列导致冲突。

分步解决:

1. 只让Web容器执行数据库迁移

修改各服务的启动命令,把migrate只放在web容器里:

  • Web服务启动命令:
    python manage.py migrate --noinput && python manage.py runserver 0.0.0.0:8000
    
  • Celery服务启动命令(只启动worker,不要migrate):
    celery -A your_project_name worker -l info
    
  • Celery-beat服务启动命令(只启动beat调度器):
    celery -A your_project_name beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler
    

2. 手动重置PostgreSQL序列(如果删库后仍有冲突)

如果删库重建后还是报序列重复,登录你的PostgreSQL服务器,执行以下命令重置auth_permission的序列:

ALTER SEQUENCE auth_permission_id_seq RESTART WITH 1;

要是想批量重置所有Django模型的序列,在web容器里执行:

python manage.py sqlsequencereset auth | python manage.py dbshell

这个命令会自动生成并执行重置序列的SQL,确保序列和表中现有数据的最大ID同步。

3. 给Celery/Celery-beat加数据库等待逻辑

哪怕web服务健康了,有时候PostgreSQL连接可能还没完全就绪(虽然你说PG不在容器里,但还是要保险)。可以写个简单的Python脚本让Celery等数据库:

# wait_for_db.py 放在项目根目录
import time
from django.db import connections
from django.db.utils import OperationalError

def wait_for_db():
    while True:
        try:
            # 尝试连接数据库
            conn = connections['default']
            conn.ensure_connection()
            print("Database is ready!")
            break
        except OperationalError:
            print("Database not ready, waiting 5s...")
            time.sleep(5)

if __name__ == '__main__':
    wait_for_db()

然后修改Celery/Celery-beat的启动命令:

# Celery启动命令
python wait_for_db.py && celery -A your_project_name worker -l info

# Celery-beat启动命令
python wait_for_db.py && celery -A your_project_name beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler

4. 确保Celery-beat只有一个实例

用数据库调度器的话,多个Celery-beat实例会同时操作数据库导致冲突,docker-compose里要保证celery-beat服务没有配置scale,只启动一个实例。

三、验证步骤

  1. 先停掉所有容器:docker-compose down
  2. 清理PostgreSQL的旧数据库,重新创建空库
  3. 重新构建容器(避免缓存问题):docker-compose build --no-cache
  4. 启动容器:docker-compose up
  5. 查看日志,确认web服务健康,Celery/Celery-beat没有迁移错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:30:20