创建发布版本后无法 运行 在 elixir 中发布应用程序
Unable to run release application in elixir after creating release build
我已经使用命令 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,elixir: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 and as this issue suggest I checked my app name and server is true set in the config file so it did not help. I have also logged issue here 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 应用程序并正确执行相同操作时 运行s 并监听端口 4000 并输出前台命令但在我的应用程序中使用相同的配置,它不监听 4000 端口并挂在前台命令上。当我看到两者的 netstat
时,我的应用程序似乎没有 运行ning 4000 端口,请参阅
我不确定我还应该如何调试这个问题我已经尝试了所有可能的方法。如果有人需要更多信息,请告诉我。在这方面,我将不胜感激 help/suggestion。
编辑:
这是我的配置和产品 files.I 刚刚粘贴了端点详细信息让我知道是否还有其他需要。
# 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
好吧,基于评论中的调试步骤,我认为我们的答案在于使用开发 phoenix 服务器时的配置与发布本身之间的差异。
配置工作方式不同的关键原因是开发服务器最常用于 运行 您机器上的本地 - 因此它很自然地 运行 关闭开发服务器上存在的环境变量机器,并在本地 运行 时间提供配置。
但是,版本旨在 运行 在远程机器上 ,通常在物理上或虚拟上与构建版本的机器不同的机器上。
这意味着严重依赖 运行时间配置的功能必须在版本中以不同方式处理。 (Several crucial values of Phoenix.Endpoint like :port, :host, etc fall under this)
随着版本的使用在 Elixir 中的发展,有几种不同的最佳实践或模式可用于弥合配置中的这种差异,这在很大程度上要归功于 Distillery。我认为今天的社区是一个非常健康的地方。
编译版本时,它无法访问最终 运行 机器的 运行 时间。因此,如果模块需要 运行time 配置,将配置委托给启动模块的 Supervisor 是一个很好的方法。在 Supervisor 初始化模块时,它已在远程机器上启动,现在可以访问该远程环境。
有两个模块我几乎总是在 supervisor 启动时配置:Ecto 的 Repo
和 Phoenix 的 Endpoint
。
实际上,您可以通过将 load_from_system_env
值设置为 true
,告诉 Endpoint
从远程计算机的 运行 时间配置自身。您需要确保通过 export PORT=4000
和 export HOST=localhost
或采购 .env
文件在环境中设置 PORT
HOST
的值,这将当 运行 发布版本和最终 运行 发布的远程机器时,本地机器上的行为相同(假设两台机器具有相同的环境值):
# config/prod.exs
config :trackbees, TrackbeesWeb.Endpoint,
load_from_system_env: true,
...
Phoenix.Endpoint is to act as a wrapper 的角色之一,用于作为监督树的一部分启动和停止端点。作为包装策略的一部分,它提供了一个 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
配置值,并可能在 if
语句 上方插入一条调试语句,如 IO.inspect
以验证该值是否正在获取通过.
仅供参考,如果您也使用 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
我已经使用命令 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,elixir: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 and as this issue suggest I checked my app name and server is true set in the config file so it did not help. I have also logged issue here 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 应用程序并正确执行相同操作时 运行s 并监听端口 4000 并输出前台命令但在我的应用程序中使用相同的配置,它不监听 4000 端口并挂在前台命令上。当我看到两者的 netstat
时,我的应用程序似乎没有 运行ning 4000 端口,请参阅
我不确定我还应该如何调试这个问题我已经尝试了所有可能的方法。如果有人需要更多信息,请告诉我。在这方面,我将不胜感激 help/suggestion。
编辑: 这是我的配置和产品 files.I 刚刚粘贴了端点详细信息让我知道是否还有其他需要。
# 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
好吧,基于评论中的调试步骤,我认为我们的答案在于使用开发 phoenix 服务器时的配置与发布本身之间的差异。
配置工作方式不同的关键原因是开发服务器最常用于 运行 您机器上的本地 - 因此它很自然地 运行 关闭开发服务器上存在的环境变量机器,并在本地 运行 时间提供配置。
但是,版本旨在 运行 在远程机器上 ,通常在物理上或虚拟上与构建版本的机器不同的机器上。
这意味着严重依赖 运行时间配置的功能必须在版本中以不同方式处理。 (Several crucial values of Phoenix.Endpoint like :port, :host, etc fall under this)
随着版本的使用在 Elixir 中的发展,有几种不同的最佳实践或模式可用于弥合配置中的这种差异,这在很大程度上要归功于 Distillery。我认为今天的社区是一个非常健康的地方。
编译版本时,它无法访问最终 运行 机器的 运行 时间。因此,如果模块需要 运行time 配置,将配置委托给启动模块的 Supervisor 是一个很好的方法。在 Supervisor 初始化模块时,它已在远程机器上启动,现在可以访问该远程环境。
有两个模块我几乎总是在 supervisor 启动时配置:Ecto 的 Repo
和 Phoenix 的 Endpoint
。
实际上,您可以通过将 load_from_system_env
值设置为 true
,告诉 Endpoint
从远程计算机的 运行 时间配置自身。您需要确保通过 export PORT=4000
和 export HOST=localhost
或采购 .env
文件在环境中设置 PORT
HOST
的值,这将当 运行 发布版本和最终 运行 发布的远程机器时,本地机器上的行为相同(假设两台机器具有相同的环境值):
# config/prod.exs
config :trackbees, TrackbeesWeb.Endpoint,
load_from_system_env: true,
...
Phoenix.Endpoint is to act as a wrapper 的角色之一,用于作为监督树的一部分启动和停止端点。作为包装策略的一部分,它提供了一个 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
配置值,并可能在 if
语句 上方插入一条调试语句,如 IO.inspect
以验证该值是否正在获取通过.
仅供参考,如果您也使用 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