1. 概述
在使用 Docker 容器化部署 Django 应用时,数据库迁移(migration)是一个常见的操作。但有时候我们会遇到 Django 无法检测到模型变更的问题,导致无法生成迁移文件。这种情况下,很多开发者会直接选择重建容器,但这显然不是最优解。
本文将通过一个完整的示例,演示如何在 Docker Compose 环境下正确执行 Django 的数据库迁移操作。我们使用 PostgreSQL 作为数据库,并在 Linux 环境下进行演示。
2. 创建 Docker 化的 Django 项目
我们先从零开始搭建一个简单的 Django 项目,并将其容器化。
2.1 创建 Django 项目
首先,创建项目目录并进入:
$ mkdir dockerized-django-app && cd dockerized-django-app
接着创建虚拟环境并安装依赖:
$ python3 -m venv venv && source venv/bin/activate && pip install django psycopg2-binary
创建 Django 项目:
$ django-admin startproject myproject .
修改 myproject/settings.py
中的数据库配置,改为使用 PostgreSQL:
from pathlib import Path
import os
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.getenv('POSTGRES_DB', 'mydatabase'),
'USER': os.getenv('POSTGRES_USER', 'myuser'),
'PASSWORD': os.getenv('POSTGRES_PASSWORD', 'mypassword'),
'HOST': 'db',
'PORT': '5432',
}
}
2.2 创建 Dockerfile
在项目根目录下创建 Dockerfile
:
FROM python:3.9
WORKDIR /app
COPY . /app
RUN pip install --no-cache-dir -r requirements.txt
EXPOSE 8000
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
同时创建 requirements.txt
文件:
django
psycopg2-binary
2.3 创建 docker-compose.yml
创建 docker-compose.yml
文件如下:
version: '3.9'
services:
db:
image: postgres
restart: always
environment:
POSTGRES_DB: mydatabase
POSTGRES_USER: myuser
POSTGRES_PASSWORD: mypassword
volumes:
- postgres_data:/var/lib/postgresql/data
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/app
ports:
- "8000:8000"
depends_on:
- db
environment:
DATABASE_URL: postgres://myuser:mypassword@db:5432/mydatabase
volumes:
postgres_data:
2.4 启动服务并执行迁移
启动服务:
$ docker-compose up -d
执行数据库迁移:
$ docker-compose run web python manage.py migrate
此时 Django 会连接 PostgreSQL 并创建初始数据库结构。
3. 处理模型变更与迁移
接下来我们演示如何添加一个新模型并执行迁移。
3.1 创建新应用
在 myproject
目录下创建 books
应用:
$ docker-compose run web sh -c "python manage.py startapp books && ls -l && mv books myproject/"
将 books
添加到 INSTALLED_APPS
中:
INSTALLED_APPS = [
...
'myproject.books',
]
同时确认 books/apps.py
中的 name
属性为 'myproject.books'
。
3.2 定义新模型
编辑 books/models.py
:
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=255)
author = models.CharField(max_length=255)
published_date = models.DateField()
def __str__(self):
return self.title
3.3 执行迁移
生成迁移文件:
$ docker-compose run web python manage.py makemigrations books
应用迁移:
$ docker-compose run web python manage.py migrate
3.4 验证模型
注册模型到 admin:
from django.contrib import admin
from .models import Book
admin.site.register(Book)
创建超级用户:
$ docker-compose run web python manage.py createsuperuser
访问 http://localhost:8000/admin/
,确认 Book
模型已注册。
3.5 Django 未检测到模型变更的常见问题
有时,Django 无法检测到模型变更,导致 makemigrations
无输出。以下是常见排查步骤:
✅ 检查模型是否已正确修改
确保字段确实有变化,例如添加了一个新字段:
class Book(models.Model):
...
isbn = models.CharField(max_length=13, unique=True) # 新增字段
✅ 执行 dry-run 检查
$ docker-compose run web python manage.py makemigrations --dry-run
如果没有输出,说明 Django 未检测到变化。
✅ 确认应用是否加入 INSTALLED_APPS
确保 myproject.books
已加入 INSTALLED_APPS
。
✅ 检查 migrations 目录是否存在
确保 books/migrations/
存在且有迁移文件。
✅ 重启容器并清除缓存
$ docker-compose down
$ docker-compose up -d
✅ 手动删除并重新生成迁移
⚠️ 注意:此操作会删除已有迁移文件,仅用于开发环境!
$ rm -rf books/migrations/*
$ docker-compose run web python manage.py makemigrations books
$ docker-compose run web python manage.py migrate
4. 总结
本文通过一个完整的 Django + PostgreSQL + Docker Compose 示例,演示了如何在容器化环境中正确执行数据库迁移操作。我们还介绍了 Django 无法检测到模型变更的常见原因及解决方法。
通过这些实践,你可以在不频繁重建容器的前提下,实现数据库结构的同步更新,提升开发效率并保障数据一致性。
完整代码可在 GitHub 上找到。