Deploy your side project in 10 minutes with Fly.io

Corentin Le Berre
abbeal’s tech blog
5 min readNov 28, 2022

In this post, I will give you the keys to deploy quickly your API online using the Fly.io platform.

First, what is Fly.io? Like classic cloud platform such as AWS/GCP/Azure, it enables you to deploy your application/api/microservices/database on the cloud. But unlike these, it stands out for its simplicity.

You can deploy a lot of different technologies such as PHP/Python/Deno/Node/Go etc out of the box or even use a Dockerfile. It’s really easy to use thanks to the CLI and documentation provided. This enables you to deploy and scale your app worldwide and close to your users without worrying about network, DNS or security. It also provides lots of metrics about your application with an integrated Graphana on your dashboard. With the free tier, you can host 2 projects.

👉 To have more details about those features just check their website

In this article, I will deploy a simple Node.js server written in Typescript enabling a beekeeper to know the state of his hives. The post will only focus on the mandatory steps for the deployment. For more information feel free to consult their documentation.

Prerequisites

Have a Node environment installed and Docker if you want to test your build locally.

Install fly cli tools 👇

Flyctl is a command-line utility that lets you work with the Fly.io platform, from creating your account to deploying your applications.

 $: brew install flyctl 
🐧$: curl -L https://fly.io/install.sh | sh
🪟$: iwr https://fly.io/install.ps1 -useb | iex

Creating our app

You can clone this project on Github or copy the code below 👇

📦 Structure of the project

📦beekeeper
┣ 📂src
┃ ┗ 📜main.ts
┣ 📜Dockerfile
┣ 📜fly.toml
┣ 📜package-lock.json
┣ 📜package.json
┗ 📜tsconfig.json

Part 1 : Create the Node.JS API

👉 Init a npm project

$: npm init

👉 Add this configuration in package.json

{
/***/
"type": "module",
"scripts": {
"dev": "ts-node src/main.ts",
"build": "rm -rf dist && tsc --build",
"start": "node dist/src/main.js"
}
/***/
}

👉 Install dependencies

$: npm install express
$: npm install -D typescript ts-node @types/node @types/express

👉 Configure Typescript compiler in tsconfig.json

{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "Node",
"esModuleInterop": true,
"rootDir": "./src",
"outDir": "./dist/src",
},
"ts-node": {
"esm": true
}
}

👉 Create the express API in src/main.ts. It’s a simple server made for a beekeeper that allows him to know the state of his hives. It exposes a single access point via /api/hives.

import express from "express";
import { Express, Request, Response } from "express";

const app: Express = express();
const port = process.env.PORT || 8080;

const bees = (n: number): string => Array(n).fill("🐝").join("");

const getHives = (req: Request, res: Response): void => {
const hives = {
"🇫🇷": bees(150),
"🇨🇦": bees(40),
"🇯🇵": bees(10),
};
res.status(200).json(hives);
};

app.get("/api/hives", getHives);

app.listen(port, () =>
console.log(`🍯 Beekeeper is running on http://localhost:${port}`)
);

You can now run the app with npm run dev

Part 2 : Build the app with Docker

⚠️ Your Docker Daemon need to be working to execute these commands

👉 Build the image locally

$: docker build -t beekeeper .

👉 Verify if the image has been created

$: docker images | grep beekeeper
beekeeper latest 2dc2439eaec3 1 min ago 118MB

👉 Test the server locally

$: docker run -it -p 8080:8080 beekeeper

You should get the state of the Hives when fetching your local endpoint 👇

State of the hives after fetching the api

Part 3 : Deploy the app worldwide

👉 Log-in or create your Fly.io account

$: flyctl auth login
$: flyctl auth signup

👉 Use the CLI to deploy the app and follow the steps below

$: flyctl launch
  • Answer no to .dockerignore
  • Define the app name to the name of your project
  • Deploy the app in the region of your choice. You can add more or change it later
  • Answer no to Postgresql and Redis database
  • Answer yes to deploy now

It may take 1 or 2 minutes to create your project and build your Docker image with Fly remote builders (optional). If it succeed, you should see this in your terminal 👇

--> Building image done
==> Pushing image to fly
The push refers to repository [registry.fly.io/beekeeper]
deployment-01GJY6F3Y3707JXJ7PTZQKFS57: digest: sha256:722fe804f091c9fd33b789ac9c06ae68af87d1e6c6720025bdb33da0bf13fe1d size: 1991
--> Pushing image done
image: registry.fly.io/beekeeper:deployment-01GJY6F3Y3707JXJ7PTZQKFS57
image size: 118 MB
==> Creating release
--> release v1 created

--> You can detach the terminal anytime without stopping the deployment
==> Monitoring deployment

1 desired, 1 placed, 0 healthy, 1 unhealthy [health checks: 1 total, 1 critical]
Failed Instances

You can detach the terminal now and check the status of your app with flyctl status.

Your app is now online ! Lets try to access it.

  • Go to your dashboard and click on the app you created.
  • You should see a lot of information about your app including the bandwidth and CPU/RAM used.
  • You should find your app url in the “Hostname” field. Click on it and add /api/hives at the end.

Tadaam, you should see lots of bees, your app is deployed 🥳 !

To redeploy the app after a change in your code or conf use fly deploy.

Conclusion

Thank you for reading this article. I focused on a simple case and the mandatory steps to deploy your application. If you need more information, feel free to check out the bonus section or the fly.io documentation.

Bonus

Configuration

The CLI tools generate for you fly.toml, a configuration file used to describe your app on their platform. Here you can define ports, env variables, deploy and runtime options, the protocol used, etc. More info here.

Example of fly.toml generated for this project 👇

# fly.toml file generated for beekeeper

app = "beekeeper"
kill_signal = "SIGINT"
kill_timeout = 5
processes = []

[env]
PORT=8080

[experimental]
allowed_public_ports = []
auto_rollback = true

[[services]]
http_checks = []
internal_port = 8080
processes = ["app"]
protocol = "tcp"
script_checks = []
[services.concurrency]
hard_limit = 25
soft_limit = 20
type = "connections"

[[services.ports]]
force_https = true
handlers = ["http"]
port = 80

[[services.ports]]
handlers = ["tls", "http"]
port = 443

[[services.tcp_checks]]
grace_period = "1s"
interval = "15s"
restart_limit = 0
timeout = "2s

Regions

You can currently deploy your apps in 26 differents regions with the command flyctl regions add.

👉 Add Paris and Tokyo as new regions

$: flyctl regions add cdg nrt

👉 Check regions

$: flyctl regions list

CI/CD

Fly provides a remote builder so it’s easy to integrate it with Gitlab or Github CI/CD pipelines. More info here and here.

--

--

Corentin Le Berre
abbeal’s tech blog

Hey, I'm Corentin 👋 I'm a fullstack developer from France