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

Docker生产环境下Django数据库无法更新的问题求助

Django+Postgres生产环境迁移失效问题解决

问题现状

生产环境使用Django和Postgres时,数据库结构无法更新:

  • 手动执行迁移命令,始终返回migrations are already applied或no changes are detected
  • 本地migrations文件夹有新增迁移文件,但服务器上的迁移未实际生效
  • 打开Django Admin面板出现数据库字段不存在的错误
  • 目前只能通过docker compose down -v删除数据库重新初始化,导致数据丢失

核心原因

你的判断正确:Git忽略了migrations目录下的实际迁移文件,仅推送了migrations/__init__.py。这引发两个关键问题:

  1. 容器构建时未包含本地生成的迁移文件,Django无法识别需要执行的迁移任务
  2. entrypoint脚本在生产环境自动执行makemigrations,生成的临时迁移与本地开发的迁移不一致,而django_migrations表已记录旧迁移状态,最终导致模型与数据库结构不匹配

可行解决办法

1. 修正Git忽略规则,提交迁移文件到版本库

不要忽略migrations下的.py迁移文件,仅忽略缓存文件。修改.gitignore:

# 保留migrations目录下的所有.py文件,只忽略缓存
*/migrations/__pycache__/
*/migrations/*.pyc
!*/migrations/__init__.py
!*/migrations/*.py

提交所有本地已生成的迁移文件到Git,确保构建镜像时这些文件被包含。

2. 调整生产环境entrypoint脚本

生产环境禁止自动执行makemigrations,迁移文件必须在本地开发时生成并提交,生产仅执行migrate。修改entrypoint.sh:

#!/bin/sh

echo "----------python migrate----------"
python manage.py migrate --noinput

echo "----------python collectstatic----------"
python manage.py collectstatic --noinput

echo "----------python runserver----------"
uvicorn config.asgi:application --host 0.0.0.0 --port 8000 & python manage.py rqworker default --with-scheduler

exec "$@"

3. 修复当前生产数据库(无需删库)

步骤1:备份数据库

先做全量备份,防止操作失误:

docker exec my_project-postgres pg_dump -U ${POSTGRES_USER} ${POSTGRES_DB} > production_backup.sql

步骤2:同步迁移文件到服务器

  • 确保本地迁移文件已提交到Git,重新构建并推送镜像
  • 拉取新镜像后重启容器,此时容器内已有正确的迁移文件

步骤3:执行迁移并修正状态

进入web容器,查看当前迁移状态:

docker exec -it ${API_CONTAINER_NAME} python manage.py showmigrations

如果有未应用的迁移,执行:

docker exec -it ${API_CONTAINER_NAME} python manage.py migrate --noinput

如果存在错误的迁移记录(比如之前自动生成的临时迁移),可针对指定应用重置后重新执行:

# 标记app_name的所有迁移为未应用
docker exec -it ${API_CONTAINER_NAME} python manage.py migrate --fake app_name zero
# 重新执行迁移
docker exec -it ${API_CONTAINER_NAME} python manage.py migrate app_name

附用户提供的配置文件

Dockerfile

FROM python:3.10-buster

RUN apt-get update

#RUN useradd -m myapp

RUN mkdir -p /home/myapp/app
WORKDIR /home/myapp/app

ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV PATH $PATH:/home/myapp/.local/bin

COPY requirements.txt .
RUN pip install --upgrade pip
RUN pip install -r requirements.txt

COPY . .

RUN chmod +x ./entrypoint.sh
ENTRYPOINT ["sh", "./entrypoint.sh"]

docker-compose.yml

version: "3.8"

networks:
  my_project_network:
    name: my_project_network

services:
  web:
    image: ${TAG_LATEST}
    container_name: ${API_CONTAINER_NAME}
    command: ["./entrypoint.sh"]
    volumes:
      - my_project_media_data:/home/myapp/app/media/
      - my_project_static_data:/home/myapp/app/static/
    restart: always
    ports:
      - 8000:8000
    networks:
      - my_project_network
    depends_on:
      - db

  db:
    image: postgres:latest
    container_name: my_project-postgres
    volumes:
      - my_project_postgres_data:/var/lib/postgresql/data/
    environment:
      - POSTGRES_DB=${POSTGRES_DB}
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_PORT=${POSTGRES_PORT}
    networks:
      - my_project_network
    restart: always

  redis:
    image: redis:latest
    container_name: my_project-redis
    ports:
      - 6379:6379
    networks:
      - my_project_network
    restart: always
    depends_on:
      - db

volumes:
  my_project_media_data:
    name: my_project_media_data
  my_project_static_data:
    name: my_project_static_data
  my_project_postgres_data:
    name: my_project_postgres_data

entrypoint.sh(原版本)

#!/bin/sh

echo "----------python makemigrations----------"
python manage.py makemigrations --noinput
python manage.py migrate --noinput

echo "----------python collectstatic----------"
python manage.py collectstatic --noinput

echo "----------python runserver----------"
uvicorn config.asgi:application --host 0.0.0.0 --port 8000 & python manage.py rqworker default --with-scheduler

exec "$@"

gitlab-ci.yml

image: alpine:3

stages:
  - build
  - deploy

variables:
  TAG_LATEST: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:latest
  TAG_COMMIT: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:$CI_COMMIT_SHORT_SHA

build:
  image: docker:latest
  stage: build
  only:
    - main
  services:
    - name: docker:dind
      alias: thedockerhost
  variables:
    DOCKER_HOST: tcp://thedockerhost:2375/
    DOCKER_DRIVER: overlay2
    DOCKER_TLS_CERTDIR: ""
  before_script:
    - chmod +x deploy.sh
    - ./deploy.sh
  script:
    - docker build -t $TAG_COMMIT -t $TAG_LATEST .
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker push $TAG_COMMIT
    - docker push $TAG_LATEST

deploy:
  stage: deploy
  only:
    - main
  before_script:
    - chmod +x deploy.sh
    - ./deploy.sh
  script:
    - chmod og= $ID_RSA
    - apk update && apk add openssh-client
    - ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP -p $SERVER_SSH_PORT "sudo docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY"
    - ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP -p $SERVER_SSH_PORT "sudo docker pull  $TAG_LATEST"
    - ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP -p $SERVER_SSH_PORT "sudo docker container rm $API_CONTAINER_NAME -f || true"
    - scp -i $ID_RSA -o StrictHostKeyChecking=no -P $SERVER_SSH_PORT -r ./.env ./docker-compose.yml $SERVER_USER@$SERVER_IP:/home/dev/projects/my_project-service
    - ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP -p $SERVER_SSH_PORT "cd /home/dev/projects/my_project-service && sudo docker compose up -d"

数据库错误截图

数据库错误截图


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 04:37:03