如何通过Distillery发布的Elixir Umbrella应用运行Ecto迁移?
实现Distillery发布包执行Ecto迁移的完整方案
针对你的Umbrella项目场景,我来帮你补全ReleaseTasks模块并梳理完整的执行流程:
1. 完善ReleaseTasks模块
因为是Umbrella项目,需要处理多个Repo的迁移,所以模块要能自动遍历所有配置的Ecto Repo。把你的模块替换成以下完整代码:
defmodule Se.ReleaseTasks do @start_apps [:postgrex, :ecto, :ecto_sql] def migrate do # 加载主应用的环境配置(替换成你的Umbrella主应用名) Application.load(:se) # 启动迁移必需的核心依赖应用 Enum.each(@start_apps, &Application.ensure_all_started/1) # 获取Umbrella项目中所有配置的Ecto Repo repos = Application.get_env(:se, :ecto_repos, []) # 遍历每个Repo执行所有未完成的迁移 Enum.each(repos, fn repo -> {:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :up, all: true)) end) # 关闭启动的依赖应用,避免残留进程 Enum.each(@start_apps, &Application.stop/1) IO.puts("✅ 所有数据库迁移执行完成!") end end
代码说明:
Application.load(:se):加载主应用配置,确保能读取到所有Repo的配置信息@start_apps:包含迁移依赖的底层组件,保证Postgrex和Ecto相关服务正常启动- 遍历
repos:自动处理Umbrella下所有应用的Repo,不用单独为每个应用写迁移逻辑
2. 配置Distillery支持自定义迁移命令
在你的rel/config.exs文件中,给release节点添加自定义命令配置:
release :se do # 保留你已有的其他配置(比如version、applications等) # 添加迁移命令映射 set commands: [ migrate: "rel/commands/migrate.sh" ] end
然后创建rel/commands/migrate.sh脚本文件,内容如下:
#!/bin/sh exec "$RELEASE_ROOT_DIR/bin/se" command Elixir.Se.ReleaseTasks migrate
记得给脚本添加执行权限:
chmod +x rel/commands/migrate.sh
3. 重新构建发布包
执行你之前的构建命令,生成包含迁移任务的新发布包:
MIX_ENV=prod mix release --env=qa
4. 执行迁移操作
解压发布包后,进入解压后的目录,直接运行以下命令即可执行所有数据库迁移:
./bin/se migrate
如果你的应用已经在运行,也可以通过RPC调用执行迁移(无需重启应用):
./bin/se rpc 'Se.ReleaseTasks.migrate()'
额外注意事项
- 确保Umbrella主应用的配置文件(比如
config/qa.exs)中,正确配置了:ecto_repos,包含所有需要迁移的Repo模块 - 确认QA环境的数据库连接信息正确,发布包能正常访问目标数据库
- 如果需要回滚迁移,可以在ReleaseTasks中添加
rollback函数,逻辑类似migrate,只需把Ecto.Migrator.run(&1, :up, all: true)改为Ecto.Migrator.run(&1, :down, all: true)(或指定版本回滚)
内容的提问来源于stack exchange,提问作者Meraj Rasool
相关产品推荐
相关产品推荐

