Как выполнить откат базы данных в docker контейнере, используя релизы elixir phoenix и пример MyApp.Release.rollback в руководствах - PullRequest
1 голос
/ 21 марта 2020

Я не могу понять, как откатить базу данных при попытке сделать это через приложение phoenix, работающее в контейнере docker. Я пытаюсь локально смоделировать, как это было бы при миграции на удаленный сервер.

Я запускаю его локально, запустив:

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

I bash в контейнер

docker exec -it 8943918c8f4f /bin/bash

cd в app/bin

cd bin

попытка отката

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

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

Если это действительно работало при запуске через приложение, оно должно взорваться, поскольку я делаю разные вещи. Но это не так.

Если я пробую eval

./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-команды

Любая помощь / направление будет принята с благодарностью.

Спасибо

Ответы [ 2 ]

3 голосов
/ 21 марта 2020

Во-первых, rpc вызов должен быть успешным. Убедитесь, что у вас действительно есть миграция в вопросе up перед запуском 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 должен запускать необходимые приложения из коробки (и это действительно происходит, согласно сообщению, которое вы получаете), поэтому я бы посоветовал вам еще раз проверить, что миграция, которую вы запрашиваете, уже завершена и вы передаете правильную версию для понижения до.

0 голосов
/ 22 марта 2020

Здесь было две проблемы, и благодаря @ aleksei-matiushkin я все заработал.

В первой проблеме не было Application.load(:my_app) в функции.

Второй проблемой было то, что Я вызывал функции отката (как мои, так и @ aleksei-matiushkin) как строку, а не как int. Теперь я называю это следующим образом: ./my_app eval 'MyApp.Release.my_rollback(20191106071140)'

Файл теперь выглядит так:

defmodule MyApp.Release do
  @app :my_app

  def migrate do
    for repo <- repos() do
      {:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :up, all: true))
    end
  end

  def rollback(repo, version) do
    setup_for_rollback()
    {:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :down, to: version))
  end

  def my_rollback(version) do
    setup_for_rollback()
    rollback(MyApp.Repo, version)
  end

  defp setup_for_rollback() do
    Application.load(@app)
    Application.ensure_all_started(:ecto_sql)
  end

  defp repos do
    Application.load(@app)
    Application.fetch_env!(@app, :ecto_repos)
  end
end

Я не уверен, что это реализация idiomati c. У меня не было никаких проблем, кроме Application.ensure_all_started(:ecto_sql), но так как это было рекомендовано, я думаю, я оставлю это.

...