Running the Application Locally
Let’s walk through working with Phoenix locally and preparing it for deployment. We can start with a brand new Phoenix application.Generate Release Config Files
We use themix release.init command to create some sample files in the ./rel directory.
Special Note on Fly Networking
Internally Fly uses IPv6 networking. This enables some cool features, but legacy Elixir applications need to be configured to work smoothly with it. These config changes tell Elixir, Phoenix, and the BEAM that we are using IPv6 addresses. The options look likeinet6 and inet6_tcp.
The next steps are how we configure that in our application.
We only need to configure rel/env.sh.eex. This file gets turned into a shell script that the release uses to set ENV values used when we run
any release commands. Here’s the important parts.
inet6_tcp for the BEAM as well.
Even if you don’t care to cluster your nodes together, you still want to do this because it enables running an IEx shell in a running node.
Docker Setup
Dockerfile
You can find a good Dockerfile ready to build your application in the hello_elixir GitHub repo. It is important to note that it uses a Debian-slim base image to build. This avoids DNS issues in Alpine images. The base elixir image is maintained by the hexpm org and is kept up to date. Hex.pm is the official package repository for Elixir. There are other options instead of Debian there as well if you prefer. The Dockerfile uses a two-stage approach. There are twoFROM commands. The first stage pulls in the source and builds the release. The second stage takes the prepared release and sets it up in a minimal Docker image. The final deployed image contains only our release.
Docker Ignore File
We add the file.dockerignore to the project with the following contents. Depending on how you COPY things into the Dockerfile, you may or may not need to configure this.
Launch the App on Fly
To launch an app on fly, runfly launch in the directory with your source code. This creates and configures a fly app for you by inspecting your source code, then prompts you to deploy.
fly.toml file first.
The fly launch command scans your source code to determine how to build a deployment image as well as identify any other configuration your app needs, such as secrets and exposed ports.
After your source code is scanned and the results are printed, you’ll be prompted for an organization. Organizations are a way of sharing applications and resources between Fly users. Every Fly account has a personal organization, called personal, which is only visible to your account. Let’s select that for this guide.
Next, you’ll be prompted to select a region to deploy in. The closest region to you is selected by default. You can use this or change to another region. You can find the list of supported regions here.
At this point, flyctl created an app for you and wrote your configuration to a fly.toml file. You’ll then be prompted to build and deploy your app. Once complete, your app will be running on fly.
Inside fly.toml
The fly.toml file now contains a default configuration for deploying your app. In the process of creating that file, flyctl has also generated a Fly-side application slot with a new name. In this case, it is fly-elixir. If we look at the fly.toml file we can see the name in there:
flyctl command will always refer to this file in the current directory if it exists, specifically for the app name/value at the start. That name is used to identify the application to the Fly platform. The rest of the file contains settings to be applied to the application when it deploys.
We’ll have more details about these properties as we progress, but for now, it’s enough to say that they mostly configure which ports the application will be visible on.
Customizing fly.toml
Elixir applications need a little customization to the generated fly.toml file.
- We added the
[deploy]setting. This tells Fly that on a new deploy, run our database migrations. The Dockerfile we’re using creates a symlink to your app name calledentry. This uses that symlink run the migrate command. - The
kill_signalis set toSIGTERM. An Elixir node does a clean shutdown when it receives aSIGTERMfrom the OS. - The
internal_portis set to 4000 for our Elixir application. The port value should match your application.
Preparing to Deploy
We’re almost there! Before we can deploy our new app, we need to setup a few things in our Fly account first. Namely, we want to provide the needed secrets and we need a database!Setting our Secrets on Fly
Elixir has a mix task that can generate a new Phoenix key base secret. Let’s use that.flyctl uses the fly.toml file to know which app we are setting the value on.
Creating our Fly Postgres Database
Attach our App to the Database
We useflyctl to attach our app to the database which also sets our needed DATABASE_URL ENV value.
Deploying to Fly
To deploy your app, just run just run:flyctl builds our Dockerfile and pushes it to a Fly container registry.
This will lookup our fly.toml file, and get the app name fly-elixir from there. Then flyctl will start the process of deploying our application to the Fly platform. Flyctl returns you to the command line when it’s done.
Viewing the Deployed App
Now that the application has been deployed, let’s find out more about its deployment. The commandfly status will give you all the essential details.
Connecting to the App
The quickest way to browse your newly deployed application is with thefly apps open command.
Special Note on Clustering
To make clustering your Elixir applications easier on Fly, in theenv.sh.eex file, the RELEASE_NODE is named using the $FLY_APP_NAME and
the IPv6 address. It will look something like this in practice.
Runtime Config
When we created the app, the fileconfig/runtime.exs was created for us. Now we need to update it.
SECRET_KEY_BASE with our Phoenix secret, our FLY_APP_NAME from Fly, and the DATABASE_URL for connecting to a Fly hosted Postgres database.
Also, you don’t need to turn on TLS for connecting to the Postgres instance. Fly private networks operate over an encrypted WireGuard mesh, so traffic between application servers and PostgreSQL is already encrypted and there’s no need to TLS.
Bonus Sections
With your application up and running, there are some additional things you can do to go further. Using someflyctl commands, we can easily do some powerful things with our application.
These bonus tips cover:
- Getting an IEx shell into your running node. This helps you manage and work with your running system.
- Clustering multiple Elixir nodes together. Say “Hello!” to the power of Distributed Computing!
- Scaling your application out to more machines and even distant regions (with or without clustering).
What is the IP Address?
If you want to know what IP addresses the app is using, tryfly ips list: