-
-
Save imranismail/83acd1b5f19959f7bca740cf36084cd3 to your computer and use it in GitHub Desktop.
Generate a Phoenix project like so:
mix phx.new - no-ecto cacaw
mix deps.get
mix phx.server
To kickoff a release lets start by adding Distillery to deps and run mix deps.get
defp deps do
[
{:phoenix, github: "phoenixframework/phoenix", override: true},
{:phoenix_pubsub, "~> 1.0"},
{:phoenix_html, "~> 2.11"},
{:phoenix_live_reload, "~> 1.0", only: :dev},
{:gettext, "~> 0.11"},
{:jason, "~> 1.0"},
+ {:cowboy, "~> 1.0"},
+ {:distillery, "~> 2.0-rc"}
]
end
Let's initialize our release config by running mix release.init
$ mix release.init
Generated cacaw app
An example config file has been placed in rel/config.exs, review it,
make edits as needed/desired, and then run `mix release` to build the release
With just that we can already cut our first release.
$ MIX_ENV=prod mix release
==> Assembling release..
==> Building release cacaw:0.1.0 using environment prod
==> Including ERTS 10.0.4 from /usr/local/Cellar/erlang/21.0.4/lib/erlang/erts-10.0.4
==> Packaging release..
Release succesfully built!
To start the release you have built, you can use one of the following tasks:
# start a shell, like 'iex -S mix'
> _build/prod/rel/cacaw/bin/cacaw console
# start in the foreground, like 'mix run --no-halt'
> _build/prod/rel/cacaw/bin/cacaw foreground
# start in the background, must be stopped with the 'stop' command
> _build/prod/rel/cacaw/bin/cacaw start
If you started a release elsewhere, and wish to connect to it:
# connects a local shell to the running node
> _build/prod/rel/cacaw/bin/cacaw remote_console
# connects directly to the running node's console
> _build/prod/rel/cacaw/bin/cacaw attach
For a complete listing of commands and their use:
> _build/prod/rel/cacaw/bin/cacaw help
We can test our release by running the first command in the output and try visiting http://localhost:4000
You'll immediately notice that it can't be reached. The reason for this is that Phoenix apps require additional configurations for OTP releases.
We could configure this in our app config that gets compiled into the release however for demonstration purpose I'm going to show you how the new Distillery makes it easy to include runtime configurations to your Elixir releases!
In Distillery 2.0 there's a new construct called Config Providers which allows us to have run time configs that are evaluated during the boot process.
These providers can come in any format. By default Distillery ships with the Elixir provider which is essentially a Mix-like config provider.
You can set them up by editing the release config in rel/config.exs
release :cacaw do
set version: current_version(:cacaw)
set applications: [
:runtime_tools
]
+ set config_providers: [
+ {Mix.Releases.Config.Providers.Elixir, ["${RELEASE_ROOT_DIR}/config/config.exs"]}
+ ]
+ set overlays: [
+ {:template, "priv/templates/config.exs.eex", "config/config.exs"}
+ ]
end
Here we are telling Distillery that we'll have an Elixir config provider available to be used.
Then we use the overlays to generate config file from a template into the release.
Let's create the template file at priv/templates/config.exs.eex
with the following content
use Mix.Config
config :cacaw, CacawWeb.Endpoint,
server: true,
root: ".",
version: Application.spec(:cacaw, :vsn)
Cut a new release, start the app with the first command and visit http://localhost:4000.
It works but now we are faced with some problems with our assets. Apparently the assets are requested from a wrong host
Let's rectify that by changing our runtime config at _build/prod/rel/config/config.exs
use Mix.Config
config :cacaw, CacawWeb.Endpoint,
server: true,
root: ".",
+ version: Application.spec(:cacaw, :vsn),
+ url: [host: System.get_env("CACAW_HOSTNAME") || "localhost", port: System.get_env("CACAW_PORT") || "4000"]
Restart the console command (the first command from the release output) and visit http://localhost:4000 and voila you've just changed a config without re-releasing a new build.
We are still having issues with the assets but we can rest assured that it is requesting from the correct host.
With this you can decouple non-deterministic configs from your application code using constructs like System.get_env/1
or delivering your artifact to the ops team to configure it to their content.
Next, lets look at including our frontend assets to the release to fix those 404 issue
When you ran your first release, it doesn't include any frontend assets. To fix this we can monkey patch our mix release
command to build our frontend assets before cutting the release.
Edit your mix.exs like so:
defmodule Cacaw.MixProject do
use Mix.Project
def project do
[
app: :cacaw,
version: "0.1.0",
elixir: "~> 1.5",
elixirc_paths: elixirc_paths(Mix.env),
compilers: [:phoenix, :gettext] ++Mix.compilers,
start_permanent: Mix.env == :prod,
+ deps: deps(),
+ aliases: aliases()
]
end
# Configuration for the OTP application.
#
# Type `mix help compile.app` for more information.
def application do
[
mod: {Cacaw.Application, []},
extra_applications: [:logger, :runtime_tools]
]
end
# Specifies which paths to compile per environment.
defp elixirc_paths(:test), do: ["lib", "test/support"]
defp elixirc_paths(_), do: ["lib"]
+
+ defp aliases do
+ [
+ "phx.digest": [&build_frontend/1, "phx.digest"],
+ release: ["phx.digest", "release"]
+ ]
+ end
+
+ defp build_frontend(_) do
+ System.cmd("yarn", ~w[run deploy], cd: "assets", into: IO.stream(:stdio, :line))
+ end
# Specifies your project dependencies.
#
# Type `mix help deps` for examples and options.
defp deps do
[
{:phoenix, github: "phoenixframework/phoenix", override: true},
{:phoenix_pubsub, "~> 1.0"},
{:phoenix_html, "~> 2.11"},
{:phoenix_live_reload, "~> 1.0", only: :dev},
{:gettext, "~> 0.11"},
{:jason, "~> 1.0"},
{:cowboy, "~> 1.0"},
{:distillery, "~> 2.0-rc"}
]
end
end
With those alterations our mix release
command will do three things:
- Builds our frontend assets which will populate the
priv
directory - Versions our frontend assets
- Builds our release with them assets included