Невозможно запустить приложение выпуска в elixir после создания сборки выпуска
Я создал сборку с помощью команды MIX_ENV=prod mix release --env=prod --verbose
, Он успешно создает сборку, и я могу запустить console
а также ping
команды и дай мне pid
, Даже когда я запускаю команду запуска, она успешно запускается, но когда я иду в htttp://localhost:4000
, сервер не работает. Когда я бегу _build/prod/rel/project/bin/project foreground
команда просто висит там без вывода.
Я использую версию MacOS: 10.13.2, эликсир: 1.6.5 (скомпилировано с OTP 19), otp: Erlang/OTP 20. Вот журнал
$ MIX_ENV=prod mix release --env=prod --verbose
Generated project app
==> Loading configuration..
==> Assembling release..
==> Building release project:0.0.1 using environment prod
==> One or more direct or transitive dependencies are missing from
:applications or :included_applications, they will not be included
in the release:
:jsx
This can cause your application to fail at runtime. If you are sure that this is not an issue, you may ignore this warning.
==> Release successfully built!
You can run it in one of the following ways:
Interactive: _build/prod/rel/project/bin/project console
Foreground: _build/prod/rel/project/bin/project foreground
Daemon: _build/prod/rel/project/bin/project start
Я уже включил все приложения, которые отображаются в качестве предупреждения, кроме jsx
потому что это показывает ошибку неопределенного приложения.
Я также прошел через проблему ликеро-водочного завода https://github.com/bitwalker/distillery/issues/276 и, поскольку эта проблема наводит на мысль, я проверил, что имя моего приложения и сервер верны в файле конфигурации, поэтому это не помогло. Я также зарегистрировал проблему здесь https://github.com/bitwalker/distillery/issues/433 более подробно.
Вот мой конфигурационный файл релиза
environment :prod do
set include_erts: true
set include_src: false
set cookie: :"lfHBC,7lDxe6kbZJ%M.x4=r!>[F*DhL)ly`?d$>%iE=9y)V4_Oulis?4Rvm)~!55"
end
# You may define one or more releases in this file.
# If you have not set a default release, or selected one
# when running `mix release`, the first release in the file
# will be used by default
release :project do
set version: current_version(:project)
set applications: [
:runtime_tools
]
end
Когда я попытался создать новое приложение Phoenix и сделать то же самое, оно работает правильно и слушает порт 4000 и выводит команду переднего плана, но с той же конфигурацией в моем приложении, оно не слушает порт 4000 и зависает на команде переднего плана. Когда я вижу netstat
для обоих кажется, что 4000 порт не работает для моего приложения см.
Я не уверен, как еще я должен отладить эту проблему, я перепробовал все, что мог. Пожалуйста, дайте мне знать, если кому-то нужна дополнительная информация. Буду признателен за любую помощь / предложение в этом отношении.
РЕДАКТИРОВАТЬ: Вот мои файлы конфигурации и Prod. Я просто вставил детали конечной точки, дайте мне знать, если что-нибудь еще нужно.
# config.exs
config :project, Project.Endpoint,
url: [host: "localhost"],
secret_key_base: some_secret_key,
render_errors: [view: Project.ErrorView, accepts: ~w(html json)],
check_origin: false,
pubsub: [name: Project.PubSub, adapter: Phoenix.PubSub.PG2]
# prod.exs
config :project, Project.Endpoint,
http: [port: 4000],
url: [scheme: "https", host: "server.example.com", port: 443],
server: true,
code_reloader: false
1 ответ
Итак, основываясь на шагах отладки в комментариях, я думаю, что наш ответ заключается в разнице между конфигурацией при использовании сервера разработки Phoenix и самой версией.
Основная причина, по которой конфигурация работает по-разному, заключается в том, что сервер разработки чаще всего предназначен для локального запуска на вашем компьютере, поэтому вполне естественно, что он запускает переменные среды, присутствующие на компьютере разработчика, и обеспечивает доступность конфигурации в локальном времени выполнения.
Однако релизы предназначены для запуска на удаленных машинах, часто на машинах, физически или практически отличных от машин, на которых был создан релиз.
Это означает, что функции, сильно зависящие от конфигурации среды выполнения, в выпуске должны обрабатываться по-разному. (Несколько ключевых значений Phoenix.Endpoint, таких как:port,:host и т. Д., Подпадают под это)
Для преодоления этой разницы в конфигурации было несколько различных передовых методов или шаблонов, поскольку использование выпусков в Elixir развивалось во многом благодаря Distillery. Я думаю, что сообщество в настоящее время действительно здоровое место.
Когда релиз компилируется, у него нет доступа к среде выполнения машины, на которой он в конечном итоге будет работать. Поэтому, если модулю требуется конфигурация во время выполнения, рекомендуется передать эту конфигурацию супервизору, который загружает модуль. В тот момент, когда Supervisor инициализирует модуль, он был загружен на удаленном компьютере и теперь имеет доступ к этой удаленной среде.
При запуске супервизора я почти всегда настраиваю два модуля: Ecto's Repo
и феникс Endpoint
,
Вы можете сказать Endpoint
настроить себя из среды выполнения удаленного компьютера, установив load_from_system_env
значение для true
, Вам нужно убедиться, что значения для PORT
HOST
устанавливаются в окружающей среде, через export PORT=4000
а также export HOST=localhost
или поиск .env
файл, и это приведет к тому же поведению на локальном компьютере при запуске выпуска и на удаленном компьютере, на котором вы в конечном итоге запустите выпуск (при условии, что обе машины имеют одинаковые значения среды):
# config/prod.exs
config :trackbees, TrackbeesWeb.Endpoint,
load_from_system_env: true,
...
Одна из ролей Phoenix.Endpoint - выступать в качестве оболочки для запуска и остановки конечной точки как части дерева Supervision. Это обеспечивает init/2
обратный вызов как часть этой стратегии упаковки. Вы увидите это, когда init/2
пожары, это будет образец совпадения на :load_from_system_env
:
# trackbees/lib/trackbees_web/endpoint.ex
def init(_key, config) do
if config[:load_from_system_env] do
Keyword.put ...
Я думаю, что это конкретное решение проблемы, с которой сейчас сталкиваются Trackbees. Я бы порекомендовал добавить load_from_system_env
значение конфигурации, и, вероятно, вставив оператор отладки, как IO.inspect
выше if
заявление, чтобы проверить значение проходит.
К вашему сведению, если вы используете Ecto, есть соответствующий init
обертка, которую вы можете использовать аналогичным образом, если вы тоже хотите:
# lib/trackbees/repo.ex
def init(_, opts) do
case Application.get_env(:trackbees, :env) do
:test ->
{:ok, opts}
_ ->
opts =
opts
|> Keyword.put(:url, System.get_env("DATABASE_URL"))
|> Keyword.put(:username, System.get_env("DB_USERNAME"))
|> Keyword.put(:password, System.get_env("DB_PASSWORD"))
|> Keyword.put(:database, System.get_env("DB_NAME"))
|> Keyword.put(:hostname, System.get_env("DB_HOSTNAME"))
{:ok, opts}
end
end