Subscribe to access all episodes. View plans →

#140: Deploying Phoenix 1.6 to Gigalixir

Published January 21, 2022

Phoenix 1.6

Gigalixir

Gigalixir CLI


In this episode we’ll create a Phoenix 1.6 application and deploy it to Gigalixir. There are 3 ways to deploy to Gigalixir. Be sure to check out the Gigalixir docs to see the benefits of each. In this Episode we’ll use the Mix method to deploy to Gigalixir.

We’ll need an application to deploy, so let’s create one. We’ll go to the command line and run: mix phx.new teacher

$ mix phx.new teacher
...

Then let’s move into the new teacher directory …. and create our app’s database with mix ecto.create.

$ cd teacher
$ mix ecto.create
The database for Teacher.Repo has been created

Now let’s test that everything is working locally. We’ll start up our server.

$ mix phx.server
...

And if we open our browser to localhost:4000 - great - our app is running. Now that we know it’s working locally, let’s get it ready to be deployed. In order to deploy our application to Gigalixir, we’ll need to first install Gigalixir’s command-line interface or CLI.

The docs have instructions for how to install the CLI and since I’m on a Mac I’ll copy the command and paste it into the terminal. Let’s confirm everything was installed with gigalixir --help and great we see all the different commands the CLI gives us.

Now if you don’t already have a Gigalixir account you can create one with gigalixir signup and you already have an account you can sign in to it with gigalixir login.

$ gigalixir login
...

Now that we’re signed into Gigalixir, let’s get our app ready to be deployed. There are really only a few changes we’ll want to make. Let’s open the config/runtime.exs and we’ll want to use SSL for our database connection. To do that let’s uncomment the the ssl: true line in our Repo config.

config/runtime.exs

...
config :teacher, Teacher.Repo,
  ssl: true,
  ...
  

Then we’ll go to our config/prod.exs and let’s force all incoming requests to our application to use SSL, redirecting HTTP to HTTPS. To do that we’ll go to the Endpoint config add force_ssl: [rewrite_on: [:x_forwarded_proto]].

config/prod.exs

...

config :teacher, TeacherWeb.Endpoint,
  force_ssl: [rewrite_on: [:x_forwarded_proto]],
  url: [host: "example.com", port: 80],
  cache_static_manifest: "priv/static/cache_manifest.json"

...

Because Phoenix 1.6 uses esbuild to compile our assets and Gigalixir images use npm we’ll need need configure npm to deploy our assets. To do that we’ll create a package.json in the /assets directory. And I’ll paste in the config from the Gigalixir docs.

assets/package.json

{
  "scripts": {
    "deploy": "cd .. && mix assets.deploy && rm -f _build/esbuild"
  }
}

Now we just need to specify the versions of Elixir, Erlang, and Node we want to deploy our app with. Let’s create an elixir_buildpack.config and inside it we’ll specify the elixir_version we want to use and the erlang_version. One note on version, you’ll probably want to use the same versions that your app is using in development and may be different than the versions I’m using here.

elixir_buildpack.config

elixir_version=1.12.3
erlang_version=22.3


Then we’ll want to create a phoenix_static_buildpack.config and we’ll specify the node_version to use.

phoenix_static_buildpack.config

node_version=12.16.3


Since Gigalixir uses git we need to create a new Git repo for our app. Then let’s add our project and commit the changes.

$ git init
$ git add .
$ git commit -m "updates for Gigalixir deploy"

Now let’s create a Gigalixir application with the name eager-reasonable-wolfspider.

$ gigalixir create
Created app: eager-reasonable-wolfspider.
Set git remote: gigalixir.
eager-reasonable-wolfspider

And confirm that it was created by running gigalixir apps.

$ gigalixir apps
[
  {
    "cloud": "gcp",
    "region": "v2018-us-central1",
    "replicas": 0,
    "size": 0.5,
    "stack": "gigalixir-20",
    "unique_name": "eager-reasonable-wolfspider",
    "version": 2
  }
]

Our app will need a database so let’s create one. Because this is a demo application we’ll use the free tier, which isn’t suitable for a production app, but will work for our example.

$ gigalixir pg:create --free
...

Let’s confirm that the DATABASE_URL and POOL_SIZE environment variables were set, which we can do with gigalixir config.

$ gigalixir config
{
  "DATABASE_URL": "ecto://...",
  "POOL_SIZE": "2"
}

Great, with that we can deploy to Gigalixir.

$ git push gigalixir master
...

It looks like everything worked. We can see from the logs that our app should now be accessible at “eager-reasonable-wolfspider.gigalixirapp.com”. Because your app will have a different name, the URL printed here will be different. Let’s open that URL - <our Gigalixir app name>.gigalixirapp.com - in the browser. And great - we see our app is deployed to Gigalixir!

This is great. Now let’s see how we can deploy changes to our application. Let’s update our app to include a blog. We’ll go back to the command line. And we’ll run mix phx.gen.html with a Blog context, a Post schema and plural posts for the table name. And let’s give our posts a title and body.

$ mix phx.gen.html Blog Post posts title body
* creating lib/teacher_web/controllers/post_controller.ex
* creating lib/teacher_web/templates/post/edit.html.heex
* creating lib/teacher_web/templates/post/form.html.heex
* creating lib/teacher_web/templates/post/index.html.heex
* creating lib/teacher_web/templates/post/new.html.heex
* creating lib/teacher_web/templates/post/show.html.heex
* creating lib/teacher_web/views/post_view.ex
* creating test/teacher_web/controllers/post_controller_test.exs
* creating lib/teacher/blog/post.ex
* creating priv/repo/migrations/{timestamp}_create_posts.exs
* creating lib/teacher/blog.ex
* injecting lib/teacher/blog.ex
* creating test/teacher/blog_test.exs
* injecting test/teacher/blog_test.exs
* creating test/support/fixtures/blog_fixtures.ex
* injecting test/support/fixtures/blog_fixtures.ex

Add the resource to your browser scope in lib/teacher_web/router.ex:

    resources "/posts", PostController

Remember to update your repository by running migrations:

    $ mix ecto.migrate

Then let’s open our router.ex and add the “/posts” resource.

lib/teacher_web/router.ex

...

scope "/", TeacherWeb do
  pipe_through :browser

  resources "/posts", PostController
  get "/", PageController, :index

end

...

Then let’s go back to the command line and migrate the database.

$ mix ecto.migrate
...

And we’ll start our server to confirm everything is working locally.

$ mix phx.server
...

Great everything looks good we can access the /posts page and create a blog post. Now let’s commit our changes.

$ git add .
$ git commit -m "adds blog"

And then to deploy our changes to Gigalixir we’ll use the same command.

$ git push gigalixir master
...

It looks like everything deployed successfully so let’s open the /posts page in production. and when we do we get an error. This is because we migrated our database in development, but haven’t done so in production. Let’s fix that. We’ll go back to the command line and to run our database migrations on Gigalixir we’ll use the gigalixir ps:migrate command.

$ gigalixir ps:migrate
...

It looks like our migrations ran. So let’s go back to the browser and if we reload the page - perfect - our app is working. We can create blog posts in our application in production.

© 2024 HEXMONSTER LLC