如何正确将Postgres数据库迁移至Docker/Django/Heroku环境
问题说明
现有托管在IIS服务器、使用PostgreSQL数据库的Django项目,计划迁移至Docker/Heroku部署架构。此前尝试使用Django内置dumpdata/loaddata功能做数据迁移,过程中持续触发约束错误、关联关系缺失、内容类型错误等问题,无法完成全流程迁移,目标是实现整库导出后全量恢复到Docker环境。
当前使用的docker-compose配置如下:
version: "3.7" services: db: image: postgres volumes: - 'postgres:/var/lib/postgresql/data' ports: - "5432:5432" environment: - POSTGRES_NAME=${DATABASE_NAME} - POSTGRES_USER=${DATABASE_USER} - POSTGRES_PASSWORD=${DATABASE_PASSWORD} - POSTGRES_DB=${DATABASE_NAME} networks: - hello-world web: build: . command: python manage.py runserver 0.0.0.0:8000 volumes: - '.:/code' ports: - "8000:8000" env_file: - .env depends_on: - db networks: - hello-world networks: hello-world: driver: bridge volumes: postgres: driver: local
迁移操作步骤
注:Django内置的dumpdata/loaddata仅适合跨数据库引擎、小批量数据的迁移场景,同PostgreSQL引擎整库迁移优先使用数据库原生备份恢复工具,可完全规避约束冲突、关联缺失、内容类型不匹配等问题。
1. 源库整库备份
- 先停止IIS上运行的Django服务,避免备份过程中有新数据写入导致备份不一致
- 在原数据库所在服务器执行备份命令,生成压缩格式的整库备份文件:
pg_dump -U <原数据库用户名> -h <原数据库地址> -p <原数据库端口> -d <原数据库名> -F c -f full_db_backup.dump
-F c参数会生成PostgreSQL自定义压缩格式备份,恢复时支持自动处理外键顺序、跳过不存在的权限配置,容错性远高于纯SQL格式备份。
2. 修正docker-compose配置错误
当前db服务配置中POSTGRES_NAME是无效环境变量,PostgreSQL官方镜像仅识别POSTGRES_DB作为初始化库名参数,修正后的db服务配置段如下:
db: image: postgres volumes: - 'postgres:/var/lib/postgresql/data' ports: - "5432:5432" environment: - POSTGRES_USER=${DATABASE_USER} - POSTGRES_PASSWORD=${DATABASE_PASSWORD} - POSTGRES_DB=${DATABASE_NAME} networks: - hello-world
3. 启动Docker端空数据库
在docker-compose.yml所在目录执行命令,仅启动数据库服务,暂不启动web服务:
docker-compose up -d db
等待30秒左右,确认数据库启动完成、可正常连接。
4. 备份恢复到Docker数据库
- 将第一步生成的
full_db_backup.dump文件放到docker-compose.yml同级目录 - 执行恢复命令:
docker exec -i <docker中db服务的容器名> pg_restore -U ${DATABASE_USER} -d ${DATABASE_NAME} --clean --if-exists --no-owner --no-privileges - < full_db_backup.dump
注:db容器名可通过
docker ps命令查看,默认命名格式为<docker-compose.yml所在目录名>_db_1
参数说明:
--clean --if-exists:恢复前自动清理已存在的同名表、对象,避免重复创建冲突--no-owner --no-privileges:跳过原库的所有者、权限绑定逻辑,适配Docker内PostgreSQL的默认用户体系,不会触发用户不存在的权限报错
5. 启动web服务验证
- 恢复完成后不要执行
python manage.py migrate:整库备份已经包含所有表结构、migration记录,重复执行migrate会触发表冲突 - 直接启动web服务:
docker-compose up -d web
- 进入容器或直接访问8000端口,验证数据完整性、页面功能是否正常即可。
Heroku迁移补充
后续迁移到Heroku时,同一份full_db_backup.dump文件可以直接通过pg_restore推送到Heroku的PostgreSQL实例,无需重复导出备份。注意Heroku生产环境需要将启动命令从开发用的runserver替换为gunicorn等生产级WSGI服务,同时提前配置好ALLOWED_HOSTS、静态文件收集相关参数。
内容的提问来源于stack exchange,提问作者K. Jones

