Build, Deploy and Run a Node Application

Getting an application running on Fly is essentially working out how to package it as a Docker image. Once packaged it can be deployed to the Fly infrastructure to run on the global application platform. For this quick start, we'll look at building a Node application from scratch.

The Hellonode Application

Our example will be a basic "hello world" example using Node and Express.

You can get the code for the example from the hellonode Github repository. Just git clone https://github.com/fly-examples/hellonode to get a local copy. Here's all the code:

const express = require("express");
const app = express();
const port = process.env.PORT || 3000;

app.get(["/", "/to/:name"], (req, res) => {
  greeting = "<h1>Hello From Node on Fly!</h1>";
  name = req.params["name"];
  if (name) {
    res.send(greeting + "</br>and hello to " + name);
  } else {
    res.send(greeting);
  }
});

app.listen(port, () => console.log(`HelloNode app listening on port ${port}!`));

We'll call this file hellonode.js and run npm init and npm install express --save so we've got the basic node setup.

Running The Application

Run node hellonode.js to start the application

node hellonode.js          
HelloNode app listening on port 3000!

And connect to localhost:3000/hello to confirm that you have a working Node application. Now to package it up for Fly.

Packaging with a Dockerfile

The Dockerfile controls how the application is composed and preserved in an image. All Docker images start with a basic image to build on. We'll be using the official Node image from the Docker official images.

FROM node:current-alpine

It'll provide all we need to package and deploy our application. The Dockerfile then sets the working directory and copies the Node/npm package files over to that directory.

WORKDIR /app

COPY package.json .
COPY package-lock.json .

With those files in place, we can get npm to download and install all the required packages.

RUN npm install --production

And then we can copy over the remaining files to the image, which will include our hellonode.js file.

COPY . .

We set the PORT environment variable to 8080:

ENV PORT=8080

8080 is the default port for applications to communicate with the outside world on Fly, so we're setting it here in the Dockerfile.

Finally, we're ready to start our application. We'll start it explicitly with node:

CMD [ "node","hellonode.js" ]

It's worth remembering this is a fairly standard Dockerfile; there are no Fly specific commands present.

Testing Locally

Now we have a Dockerfile, we can build our application as a local image to ensure it works as expected. Run docker build -t hellonode .

Running docker run -p8080:8080 hellonode will run the hellonode image locally. You can then connect to http://localhost:8080/ to view see the Hello from Fly message.

For the curious: The -p8080:8080 exposes port 8080 locally so you can connect; by default, all ports are closed.

Install Flyctl

We are ready to start working with Fly and that means we need flyctl, our CLI app for managing apps on Fly. If you've already installed it, carry on. If not, hop over to our installation guide

Sign In (or Up) for Fly

If you have a Fly account, all you need to do is sign-in with flyctl.

New User?

Welcome to Fly. To get your Fly account run:

flyctl auth signup

This will take you to the sign-up page where you can either:

  • Sign up with Email: Enter your name, email and password.

  • Sign up with Github: If you have a Github account, you can use that to sign up. Look out for the confirmatory email we will send you which will give you a link to set a password; you'll need a password set so we can actively verify that it is you for some Fly operations.

Returning User

Run:

flyctl auth login

Your browser will open up with the Fly sign-in screen. Enter your user name and password to sign in. If you signed up with Github, use the Sign in with Github button to sign in.

Whichever route you take you will be signed-up, signed-in and returned to your command line, ready to Fly.

Configuring the App for Fly

Each Fly application needs a fly.toml file to tell the system how we'd like to deploy it. That file can be automatically generated with the command flyctl apps create command.

flyctl apps create
? App Name (leave blank to use an auto-generated name) hellonode
? Select organization: Dj (dj)
New app created
  Name     = hellonode
  Owner    = dj
  Version  = 0
  Status   =
  Hostname = <empty>

Wrote config file fly.toml

Note: We recommend that you go with the autogenerated names for apps to avoid namespace collisions. We're using hellonode here so you can easily spot it in configuration files.

The fly.toml file now contains a default configuration for deploying your app. In the process of creating that file, flyctl has also created a Fly-side application slot of the same name, "hellonode". If we look at the fly.toml file we can see the name in there:

app = "hellonode"

[[services]]
  internal_port = 8080
  protocol = "tcp"

  [services.concurrency]
    hard_limit = 25
    soft_limit = 20

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

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

  [[services.tcp_checks]]
    interval = 10000
    timeout = 2000

The 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 will be 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.

Deploying to Fly

We are now ready to deploy our containerized app to the Fly platform. At the command line, just run:

flyctl deploy

This will lookup our fly.toml file, and get the app name hellonode from there. Then flyctl will start the process of deploying our application to the Fly platform. Flyctl will return you to the command line when it's done.

Viewing the Deployed App

Now the application has been deployed, let's find out more about its deployment. The command flyctl info will give you all the essential details.

flyctl info
App
  Name     = hellonode
  Owner    = demo
  Version  = 0
  Status   = running
  Hostname = hellonode.fly.dev

Services
  TASK   PROTOCOL   PORTS
  app    tcp        80 => 8080 [HTTP]
                    443 => 8080 [TLS, HTTP]

IP Addresses
  TYPE   ADDRESS                               CREATED AT
  v4     77.83.140.182                         27s ago
  v6     2a09:8280:1:8c5:fdcf:3326:e0d9:c334   27s ago

Connecting to the App

Remembering to replace hellonode.fly.dev with the hostname you got from flyctl info and with your application deployed, open your browser and connect to http://hellonode.fly.dev where you should find a greeting. Use https://hellonode.fly.dev to connect to it securely. Add /to/name and you'll get an extra greeting from the hellofly application.

Bonus Points

  • When our Dockerfile is run, it copies everything from the directory over to the Docker image. For Node applications, some directories like node_modules are going to be rebuilt anyway so there's no need to copy them. Create a .dockerignore file and add node_modules to it to do this.
  • You can also use the .dockerignore to skip unused project assets and any other files which aren't needed at runtime.

Arrived at Destination

You have successfully built, deployed and connected to your first Node application on Fly.