We like Elixir & Phoenix, and we like Heroku. So one day we thought: why not combine them? In today’s post we talk about how to deploy a Phoenix app to Heroku.
Phoenix is framework for the Elixir language, used to build fast, scalable web applications. Because Elixir runs on the Erlang Virtual Machine, it’s able to fully use all CPU cores without sacrificing code readability, robustness and security. It proves its values in low-latency, distributed and fault-tolerant systems. How many times have you heard: “Your call cannot be made at the moment because we are upgrading our servers”? Never? That’s because Erlang was created by Ericsson for handling these needs, within the context of telecommunication systems.
Then, on the other side, you have Heroku: a powerful platform for hosting applications written in multiple languages; Ruby, Python, Node.js, and Go, among others. It makes deploying, scaling and hosting a breeze.
Unfortunately Heroku by default does not support apps written in Elixir out of the box at the moment of writing. Luckily there are many 3rd party buildpacks that are compatible with Heroku’s official ones and can be used as a replacement or addon. In this article we will show you how to deploy Phoenix application using those extra buildpacks.
We assume you already have a Heroku account and a Phoenix application created.
Create an application on Heroku
In your application folder, create a Heroku app:
heroku create your-application-name --buildpack "https://github.com/HashNuke/heroku-buildpack-elixir.git"
Remember that your name has to be unique on Heroku.
If you need to compile assets (JS, CSS, etc.) as part of your deployment (not needed i.e. for API apps), you will also need to add the phoenix-static buildpack:
heroku buildpacks:add https://github.com/gjaldon/heroku-buildpack-phoenix-static.git --app your-application-name
Configuration
Preparing the application for deployment
Modify your configuration files:
# config/prod.exs
config :heroku_phoenix, HerokuPhoenix.Endpoint,
http: [port: {:system, "PORT"}],
url: [scheme: "https", host: "your-application-name.herokuapp.com", port: 443],
force_ssl: [rewrite_on: [:x_forwarded_proto]],
cache_static_manifest: "priv/static/manifest.json",
secret_key_base: System.get_env("SECRET_KEY_BASE")
# Configure your database
config :heroku_phoenix, HerokuPhoenix.Repo,
adapter: Ecto.Adapters.Postgres,
url: System.get_env("DATABASE_URL"),
pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
ssl: true
Remember to replace `your-application-name.herokuapp.com` with your actual app name.
Change the websocket timeout so Phoenix will close them before Heroku does (55 seconds):
# web/channels/user_socket.ex
defmodule HerokuPhoenix.UserSocket do
use Phoenix.Socket
# ...
transport :websocket, Phoenix.Transports.WebSocket,
timeout: 45_000
end
Create Procfile in your project root directory to instruct the dyno how to start your app:
web: MIX_ENV=prod mix phoenix.server
Heroku configuration
Add a database to your Heroku app:
heroku addons:create heroku-postgresql:hobby-dev
# hobby-dev package allows for 20 open connections - we want 18 for our app server dyno so remaining 2 can be used by migrations or iex console:
heroku config:set POOL_SIZE=18
We also need to generate a secret key for Heroku:
heroku config:set SECRET_KEY_BASE=$(mix phoenix.gen.secret)
Deployment
Now you can push to the app to Heroku with `git`.
*Note*: Heroku will only build from the master branch, to build from a different branch use:
git push heroku master:different_branch
After deployment is finished you just need to migrate the db:
heroku run "POOL_SIZE=2 mix ecto.migrate"
Useful commands
heroku logs (use --tail if you want to tail them) - check logs
heroku run "POOL_SIZE=2 iex -S mix" - enter to the console
Troubleshooting
In case of any compilation errors, try to force a build by adding `elixir_buildpack.config` file at the application root with the following content:
always_rebuild=true
We know all sorts of hints and tricks for configuring your software systems - and when we don’t have the answer we sure do love a challenge! If you would like to run your web application more effectively then make sure to get in contact with us at iRonin. We help business and software companies in the USA and around the world build faster, smoother, and more reliable systems.