Skip to content

Latest commit

 

History

History
355 lines (239 loc) · 11.8 KB

elixir-phoenix-app-deployment.md

File metadata and controls

355 lines (239 loc) · 11.8 KB

Deploying an Elixir/Phoenix App to Heroku

heroku-phoenix-logo

Why?

You want to deploy your Web Application with Database to Heroku as fast as possible while still understanding all the steps!

What?

A step-by-step guide to deploying a (Phoenix) Web App on Heroku.

We created this walkthrough/tutorial while deploying our "beginner phoenix example": https://github.com/dwyl/phoenix-chat-example
So we know it works! Try it: https://phxchat.herokuapp.com

Note: most of this is applicable to any App (Node.js, Python, Ruby, etc.)
Even if you are deploying a totally different Language/Framework, it's still worth "skimming".

Who?

Anyone who wants a quick, easy and "free" way to deploy a demo app!

How?

First, let's do the setup on Heroku:

1. Create a New App

Once you have logged into your Heroku account and are viewing your "dashboard": https://dashboard.heroku.com

1.1 Click on the New button, then
1.2 Click on Create new app:

heroku-create-app

2. Give Your New App a Name

Input your desired name (if it's available; otherwise get creative!):
heroku-new-app-name-defaults
In this case we are creating an App called phxchat. (short for Phoenix Chat, because obviously phoenixchat is "taken"...)

Leave the rest of the options to the "default" options (unless you have specific needs).

Note: don't worry about the "Add to pipeline" option for now, we will come back to it later.

Click on the Create app button.

You will be directed to the "Deploy" tab for your app:
heroku-phx-chat-dwploy-tab

3. Create "Deployment Pipeline"

On the "Deploy" tab of your app, scroll down till you see the "Deployment Method" section:

heroku-deploy-connect-to-github-connect

  1. Click on "GitHub"
  2. Select the "Owner" of the App you want to deploy (usually your own GitHub username)
  3. Type (or copy-paste) the name of your App.
  4. Click Search to find the repo.
  5. Click "Connect" button.

You should see:
heroku-app-connected

4. Add the PostgreSQL Database "Add-on"

Given that our Phoenix App uses a Postgres database to store it's data, let's add it as an "Add-on".

Scroll to the top of the dashboard and click on the "Resources" tab:

click-on-resources-tab

On the "Resources" page, scroll down till you See "Add-ons"

heroku-addons-select-postgres

  1. Type: "post" (in the add-on search input box)
  2. Select "Heroku Postgres" from the list.

This will open a "Modal" for you to confirm:
heroku-postgres-select-default

Leave the default "Hobby Dev - Free" and click the "Provision" button.

You should now see (something similar to) the following:
heroku-addon-installed

5. Create a elixir_buildpack.config File

In the root directory of the App you are trying to deploy, create a file called elixir_buildpack.config

Paste the following lines into the file:

# Latest version of Erlang/OTP see: https://git.io/Je5k6
erlang_version=22.2

# Latest Elixir Version see: https://github.com/elixir-lang/elixir/releases
elixir_version=1.9.4

# Always rebuild from scratch on every deploy?
always_rebuild=false

# Set the path the app is run from
runtime_path=/app

This file overrides the default options defined by adding the buildpack in Step 9 (below). For more detail on the configuration options for your elixir_buildpack.config file see: https://github.com/HashNuke/heroku-buildpack-elixir#configuration

6. Create a Procfile File

Also in the root directory of your App, create a file called Procfile

Paste this line in the file:

web: MIX_ENV=prod mix ecto.migrate && mix phx.server

That will ensure that your database tables/schema is up-to-date before trying to launch the app.

7. Update Your prod.exs File

This section "borrows liberally" from: https://hexdocs.pm/phoenix/heroku.html#making-our-project-ready-for-heroku

7.1 Configure the Endpoint Section

The default looks something like this:

config :chat, ChatWeb.Endpoint,
  load_from_system_env: true,
  url: [host: "example.com", port: 80],
  cache_static_manifest: "priv/static/cache_manifest.json"

Update the following params: url, force_ssl and secret_key_base:

config :chat, ChatWeb.Endpoint,
  load_from_system_env: true,
  url: [scheme: "https", host: "phxchat.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")

Where:

  • The first line remains the same (dependent on the name of your app)
  • The url should be your heroku app name (in our case phxchat)

7.2 Create a Repo Section

By default prod.exs does not have a Repo section, so we need to create one. Here's a "template"

# Configure your database
config :hello, Hello.Repo,
  adapter: Ecto.Adapters.Postgres,
  url: System.get_env("DATABASE_URL"),
  pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
  ssl: true

The one for our "chat" application is:

# Configure your database
config :chat, Chat.Repo,
  adapter: Ecto.Adapters.Postgres,
  url: System.get_env("DATABASE_URL"),
  pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
  ssl: true

All that changes is the first line which is the name of your app.

7.3 Comment out Last Line in prod.exs

Given that we are storing our "secrets" as Environment Variables on Heroku. We can safely comment out the line in prod.exs:

import_config "prod.secret.exs"

becomes:

# import_config "prod.secret.exs"

8. Generate the SECRET_KEY_BASE String

The SECRET_KEY_BASE is the key that your app will use to digitally sign request tokens. It's vital to keep it a secret to avoid "compromising" your app. Therefore we will store it in an Environment Variable on Heroku.

8.1 Run the mix phx.gen.secret Command

On your localhost (terminal), run the following command:

mix phx.gen.secret

That will output a 64 character String such as:

khaO4IJvSa+AFJHGFzlsgVlOuNNLgrUg9D4PCD943tKqersy3YNtABh/zmqd/v7y

Copy that string to your clipboard. (we will use it in the next step)

8.2 Define the SECRET_KEY_BASE Environment Variable on Heroku

Note: if you are new to Environment Variables, we recommend you read our "complete beginner" tutorial: github.com/dwyl/learn-environment-variables

Open the "Settings" Tab of your App's Heroku Dashboard: heroku-settings-tab

Now scroll down to the "Config Variables" and click on the "Reveal Config Vars" button:

heroku-reveal-config-variables

This will display your existing variable DATABASE_URL and allow the creation of new Environment Variables.

heroku-add-secret_key_base-config-var

  1. Set the "key" for the variable: SECRET_KEY_BASE
  2. Paste the value generated in step 8.1 (above)
  3. Click the "Add" button

9. Add the Elixir "Buildpack"

Still in the "Settings" Tab of the Heroku Dashboard for the App, Scroll down to the "Buildpacks" section:

heroku-add-buildpacks

Click on the "Add buildpack" button.

A "Buildpack" tells Heroku how to run your app. In the case of an elixir app it defines how to get the dependencies and what the app expects/requires.
For more detail, see: https://devcenter.heroku.com/articles/buildpacks

When the "Modal" opens:

heroku-add-elixir-buildpack

  1. Paste the value: https://github.com/HashNuke/heroku-buildpack-elixir.git into the field.
  2. Click on "Save change" button

You should now see the following:

heroku-buildpack-added

9.1 Repeat

In order to compile any "static assets" (JS/etc.) we need to add a second buildpack: https://github.com/gjaldon/heroku-buildpack-phoenix-static.git

Repeat the process you just went through but this time add the heroku-buildpack-phoenix-static buildpack.

Great! Now onto the final step!

10. (Manually) Deploy

Don't worry, you only have to do this once.
All subsequent deploys are automatic!

Back on the "Deploy" tap of your App's Dashboard, Scroll down to the "Manual deploy" section:

heroku-manual-deploy

Click on the "Deploy Branch" button.

This will start the build process. Heroku will show you the "build log":

heroku-build-log

Once the build is complete, click on the "Open App" button in the top-right of your Heroku dashboard: open-app

You should see your app running in the browser!

In our case the app is: https://phxchat.herokuapp.com phxchat

done()



Why Not use the "Official" Deployment Guide?

We are aware of (and have read) the "Deploying on Heroku" guide: https://hexdocs.pm/phoenix/heroku.html
It's a good guide for people with "intermediate" Heroku skills, however it's longer (more steps) than this tutorial, uses the Heroku "Toolbelt" (Command Line Interface "CLI"), which most "beginners" don't have installed and does not setup a "deployment pipeline" so it's a "manual" job (running the deploy command each time).

With that said, it is a good reference, so if you are stuck, that is a good place to look for "trouble-shooting".

References & Background Reading