首页 > 解决方案 > 如何使用 elixir phoenix 版本和指南中的示例 MyApp.Release.rollback 在 docker 容器中回滚数据库

问题描述

当尝试通过在 docker 容器中运行的 phoenix 应用程序来回滚数据库时,我无法弄清楚如何回滚数据库。我正在尝试在本地模拟在远程服务器上迁移时的情况。

我通过运行在本地运行它:

docker run -it -p 4000:4000 -e DATABASE_URL=ecto://postgres:postgres@host.docker.internal/my_app_dev -e SECRET_KEY_BASE=blahblah my-app-tag:v1

我查看正在运行的容器:

docker ps

我冲进容器

docker exec -it 8943918c8f4f /bin/bash

光盘进入app/bin

cd bin

尝试回滚

./my_app rpc 'MyApp.Release.rollback(MyApp.Repo, "20191106071140")'

=> 08:43:45.516 [info]  Already down

如果这在运行应用程序时确实有效,它应该在我做不同的事情时爆炸。但事实并非如此。

如果我尝试评估

./my_app eval 'MyApp.Release.rollback(MyApp.Repo, "20191106071140")'

=>

08:46:22.033 [error] GenServer #PID<0.207.0> terminating
** (RuntimeError) connect raised KeyError exception: key :database not found. The exception details are hidden, as they may contain sensitive data such as database credentials. You may set :show_sensitive_data_on_connection_error to true when starting your connection if you wish to see all of the details
    (elixir) lib/keyword.ex:393: Keyword.fetch!/2
    (postgrex) lib/postgrex/protocol.ex:92: Postgrex.Protocol.connect/1
    (db_connection) lib/db_connection/connection.ex:69: DBConnection.Connection.connect/2
    (connection) lib/connection.ex:622: Connection.enter_connect/5
    (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Last message: nil
** (EXIT from #PID<0.163.0>) shutdown

我试图确保我知道如何将应用程序部署到远程(Heroku、AWS)并让应用程序在每次部署时自动迁移,但也可以选择运行命令以一次回滚 1 步。

我没有找到任何信息。上面的调试是在远程服务器上创建此迁移/回滚功能的第一步,但首先在我的本地计算机上进行测试。

迁移/回滚代码直接取自https://hexdocs.pm/phoenix/releases.html#ecto-migrations-and-custom-commands

任何帮助/方向将不胜感激。

谢谢

标签: dockerelixirphoenix-frameworkdatabase-migrationecto

解决方案


首先,rpc调用应该成功。确保在运行之前确实有问题中的迁移my_app rpc请注意,第二个参数是要恢复的版本,而不是要恢复的迁移

关于eval. 在尝试访问其配置之前,应该start或至少是应用程序。load根据文档

您可以通过调用来启动应用程序Application.ensure_all_started/1。但是,如果由于某种原因您无法启动应用程序,可能是因为它会运行您不想要的其他服务,您至少必须通过调用Application.load/1. 如果您不加载应用程序,任何读取其环境或配置的尝试都可能失败。请注意,如果您启动一个应用程序,它会在启动前自动加载。

为了迁移成功,需要Ecto启动应用Ecto.Adapters.SQL.Application程序加载您的应用程序(以访问配置。)

也就是说,这样的事情应该有效。

def my_rollback(version) do
  Application.load(:my_app)
  Application.ensure_all_started(:ecto_sql)
  Ecto.Migrator.with_repo(MyApp.Repo,
    &Ecto.Migrator.run(&1, :down, to: version))
end

并将其称为

./my_app eval 'MyApp.Release.my_rollback(20191106071140)'

尽管如此,rpc应该开箱即用地启动所需的应用程序(确实如此,根据您返回的消息,)所以我建议您再次检查您请求的迁移是否已经启动并且您通过要降级到的正确版本。


推荐阅读