已完成迁移仍检测到重复迁移,Django预生产部署失败
问题原因
你遇到的问题根源有两个:
- 部署时自动生成迁移+删除数据库卷:每次部署执行
docker-compose down -v会彻底删除PostgreSQL的数据卷,导致数据库里的迁移历史表(django_migrations)被清空。而你的entrypoint脚本每次启动都跑makemigrations --noinput,Django会对比当前模型和空数据库,重新生成和上月完全一样的迁移文件。 - 重复迁移执行冲突:当你再次执行
migrate时,新生成的迁移会尝试删除已经在上月删除的字段,自然报错。
解决方案
1. 修正部署流程,保留数据库迁移历史
把部署步骤里的down -v改成down(去掉-v参数):
sudo docker-compose -f docker-compose.preprod.yml down git pull sudo docker-compose -f docker-compose.preprod.yml up -d --build --remove-orphans sudo docker-compose -f docker-compose.preprod.yml up
-v会删除挂载的卷,包括PostgreSQL的数据存储,这会丢失所有数据库数据和迁移记录,预生产环境绝对不能这么操作。
2. 修改entrypoint.sh,禁止部署时自动生成迁移
迁移文件应该在本地开发完成后,手动生成并提交到Git仓库,部署时只需要执行migrate即可。把entrypoint里的python manage.py makemigrations --noinput删掉:
#!/bin/sh if [ "$DATABASE" = "postgres" ] then echo "Waiting for postgres..." while ! nc -z $SQL_HOST $SQL_PORT; do sleep 0.1 done echo "PostgreSQL started" fi python manage.py migrate exec "$@"
3. 修复当前预生产环境的错误状态
如果现在预生产数据库已经因为down -v被清空,或者迁移状态混乱,可以按以下步骤修复:
- 先确保本地仓库里有上月生成的正确迁移文件(就是之前已经应用过的那些)
- 启动容器后,进入Django容器:
sudo docker-compose -f docker-compose.preprod.yml exec web bash
- 标记所有已存在的迁移为已应用(避免重复执行):
python manage.py migrate --fake
- 如果数据库是空的,也可以直接重新应用所有迁移(适合数据可以重新导入的情况):
python manage.py migrate
额外建议
- 预生产环境的数据库数据和迁移记录必须持久化,永远不要用
down -v除非你明确要彻底清空环境。 - 迁移文件属于代码的一部分,必须和模型修改一起提交到Git,部署时只执行
migrate,不要在服务器上生成迁移。
内容的提问来源于stack exchange,提问作者Mereva
相关产品推荐
相关产品推荐

