Fly.io — Deployment so easy even Donald Trump can do it

Ondřej Popelka
5 min readDec 6, 2023

I had a crazy idea for an app that does absolutely nothing useful, but I was so proud of it that I couldn’t just keep it hidden in GitHub. I wanted to share it with the world and let everyone experience how amazingly magnificently pointless it is.

This is not him

So I became looking for deployment options. I have no problem with deploying an application, I do it as part of my everyday work. I have accounts on all of the Big Three (or was it Fantastic Four ?) — Azure, AWS, GCP. Given a Dockerfile setting up a deployment is a nobrainer. I don’t have any Kubernetes cluster at hand so let’s just stick together some ARM template to run it on using Azure Container App or CloudFormation template and run it as using AWS Elastic Container Service or something like that. But that’s all in the past. I stopped hating Terraform weeks ago, so let’s start with an S3 bucket to store the Terraform remote state.

Stop Right There Police, @kindpng.com

Yeah, stop right there. This thing is not supposed to be a nuclear power plant. The application is not going to get used at all. In fact I don’t want to spent more than zero time on it and preferably even less money. Let’s look one level higher.

Heroku ? Nah, too Ruby, plus no free offering currently. Platform.sh ? Nah, to Bashy, plus no free offering currently. Someone on a meetup pointed me to Fly.io as a “you definitely have to try this” thing.

Let’s Fly

Let’s create an account then and install the CLI. Follow the instructions:

> fly auth login
> fly launch

Answer a couple of questions. Crunch Crunch 🍪.

...
Visit your newly deployed app at https://ronum.fly.dev/

OK, so it is basically done before you can say “Azure Resource Group” let alone write a Bicep (because ARM is sooo out of fashion) template and run it. Saying that is it is amazing just does not cut it. This thing is h**y f***ing awesome!

The CLI tool creates a fly.toml configuration which stores all the things I entered during the setup. I don’t have to enter that again, yay! The application runs, let’s check the monitoring.

Application overview

Cool, the memory usage is as expected (around 100MB), the traffic is as expected (close to none). The bill is zero, that’s also cool. Fly also offers Grafana for monitoring. My app is not going to get used and there is no traffic, so there are no interesting data to see, but all the important metrics are present.

Detailed monitoring

Even though I’m on the free offering I do not wish to waste any resources. A little fine tuning in the fly.toml config file cuts the application footprint to close-to-nothing by setting auto_stop_machines=true and min_machines_running=0 .


app = "ronum"
primary_region = "ams"

[build]

[http_service]
internal_port = 8501
force_https = true
auto_stop_machines = true
auto_start_machines = true
min_machines_running = 0
processes = ["app"]

This way the app scales down to zero machines in few minutes (unspecified in the docs, but seems to be something between 5 and 10). Cold start takes 4–5 seconds. What else does the config file offer is also really cool:

  • HTTPS — ✔️Just turn it on, TLS options configurable;
  • Deploy strategy — ✔️Feel free to choose from rolling, canary, immediate and blue-green;
  • Docker build options — ✔️Multistage Dockerfile supported;
  • Mounts & VM settings — ✔️Set whatever you want, GPU included;
  • Ton of other stuff — ✔️

I can now go boasting how lovely Fly.io looks and how well and fast it works. Scaling the app? Just say fly scale count 2 and done, it is just missing a connection to my brain. But I’ll save all that enthusiasm for some other more resource heavy and more complex application.

CI/CD Integration

At this moment I’m not at all surprised, that there is a ready working GitHub action. I can deploy the straight from GitHub actions workflow file. There is also a tutorial in the docs but it’s not really need. Setting up the workflow is as straightforward as it can get. This is my entire workflow:

name: GitHub Actions
on: [ push ]
concurrency: ci

env:
APP_NAME: "ronum"
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v3

- name: Build
run: |
docker build -t "$APP_NAME" .

- name: Test
run: |
docker run "$APP_NAME" python -m flake8
docker run "$APP_NAME" python -m unittest --verbose

deploy:
name: Deploy app
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v3
- uses: superfly/flyctl-actions/setup-flyctl@master

- run: flyctl deploy --remote-only
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}

There is also a Terraform provider, but currently not maintained so I didn’t bother to try it. Seems worth following though.

My first impression on Fly.io ? Big Wow. The speed is awesome, the CLI works like a charm. The ease of use is excellent. And as a bonus, there is an exceptionally interesting blog which contains some very interesting stuff about the Fly.io internals.

I know, we’ve been waiting for this guy the whole time.

--

--