Deploying a Phoenix app to Heroku
Mark
Posted on May 11, 2019
In this quick guide, we'll build a new Phoenix app, set up Heroku and deploy! Heroku may not be the ideal choice for an Elixir app but Elixir and Phoenix is an ideal stack to run on Heroku!
If you haven't already installed and set up Elixir on your computer, go through the setup part of lesson 1 and then you'll be ready to follow along here. These are the steps we'll go over:
- Sign up for Heroku (here)
- Install the Heroku Toolbelt (download here)
- Create a new Phoenix app
- Create a new app for it on Heroku
- Add the Phoenix static buildpack
- Create a free tier database on Heroku
- Change some settings in our project
- Make a
Procfile
andelixir_buildpack.config
for Heroku - Push everything to Heroku to deploy!
Quick start
We'll call our app Hello
, so here's what we need to run:
mix phx.new hello
cd hello
git init
heroku create --buildpack "https://github.com/HashNuke/heroku-buildpack-elixir.git"
heroku buildpacks:add https://github.com/gjaldon/heroku-buildpack-phoenix-static.git
heroku addons:create heroku-postgresql:hobby-dev
Application files to change
Heroku stores secrets in system environment variables instead of a secrets file, so we can delete prod.secrets.exs
. Then, we can update prod.exs
to get the secrets we need from System.get_env
. While we're there we can also set the app to use SSL and update the host name to whatever Heroku named our app when we created it. Finally add the database settings to the bottom of the file:
use Mix.Config
config :hello, HelloWeb.Endpoint,
load_from_system_env: true,
url: [scheme: "https", host: "NAME_OF_HEROKU_APP.herokuapp.com", port: 443],
force_ssl: [rewrite_on: [:x_forwarded_proto]],
cache_static_manifest: "priv/static/cache_manifest.json",
secret_key_base: Map.fetch!(System.get_env(), "SECRET_KEY_BASE")
# Do not print debug messages in production
config :logger, level: :info
# Configure your database
config :hello, Hello.Repo,
adapter: Ecto.Adapters.Postgres,
pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
ssl: true,
url: System.get_env("DATABASE_URL")
If your app is going to use channels, then update your user_socket.ex
file to add a timeout for sockets. Heroku limits them to 55 seconds, so set the time out to something like 45 seconds to be safe:
transport(:websocket, Phoenix.Transports.WebSocket, timeout: 45_000)
Application settings for Heroku
By default Phoenix uses a pool size of 10. This is very low and ideally we want to use nearly as much as is available. On Heroku we have a maximum pool of 20, so we'll set our application to use 18 and just use 2 for mix tasks. We'll also generate a secret key with Phoenix and set that in Heroku so that the app can get it from the system environment in production:
heroku config:set POOL_SIZE=18
heroku run "POOL_SIZE=2 mix hello.task"
mix phx.gen.secret
heroku config:set SECRET_KEY_BASE="<SECRET PHOENIX JUST GENERATED ABOVE>"
New files to add
In the root directory of our app, we'll add two more files for Heroku—one called Procfile
that has just one line:
web: MIX_ENV=prod mix phx.server
and one called elixir_buildpack.config
that holds some configuration settings:
erlang_version=20.1
elixir_version=1.7.2
always_rebuild=false
runtime_path=/app
Important: Make sure that both files have LF line endings. Heroku throws errors on CRLF!
Deploy!
git add .
git commit -m "prepares for heroku"
git push heroku master
Originally published at Alchemist Camp
Posted on May 11, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.