Skip to content
Flutter Explained
TwitterVideosProducts

Deployment of a Dart Server on Heroku

DevOps, Dart, Backend5 min read

Running the first server is a fantastic experience for every developer. It gives you many options and possibilities and improves your general understanding of software engineering. After we learned in my previous videos already how to start a server locally, we want in this article to learn how to make our services available on the world wide web so that you can access them from every device.

Deployment

Software deployment includes all activities that make a software system available to use. - Wikipedia

In our use case, we want to access our server from every device connected to the Internet and not only our local device in front of us. In professional teams, that task is automated in most cases and transforms quickly. Into continuous deployment where you work on your code, push to a repository, and the deployment gets automatically triggered. But in smaller teams or smaller organizations, the preferred way is usually for a skilled professional to perform that task. And because we are skilled professionals, we do exactly that today.

Prerequisites

We have to prepare just a few things to get started in the beautiful world of deployment. The first thing that we need is a physical server that will run our software server :). For this reason, we will use Heroku, because it allows us to run our software for free in a small server Virtual Machine (VM) that we can scale up if we want.

We also need a software service that we already built in the videos mentioned above. The service we want to deploy will use the shelf server from Dart that we already run locally and make our first requests. But this will also work if you use a aqueduct server or a conduit server.

Summary of what we need today:

  1. Heroku Account
  2. Running Software Server
  3. No previous knowledge about deployment processes

Getting started

After you successfully create an account on Heroku, you will probably see a page that welcomes you to Heroku. From here, you could also create a new app, but we will do it with the Heroku CLI.

Heroku CLI

Now that we have that covered let us jump right into it. To begin our journey to deploy something on Heroku, we need to install the Heroku CLI. Then, check out the link of the Heroku CLI and select the system that fits your operating system.

Great, the Heroku CLI will help us deploy our Server to the Heroku server. After the installation, we first have to login against the Heroku system. For that, execute Heroku login in your terminal. After executing the command, your default web browser will open and allow you to log in to Heroku.

Create a new Heroku app

The most convenient way to create a new Heroku app is via the CLI. For that, open a terminal and navigate to your workspace in which your project is. In our example, it will be in ~/dev/dart-server. Now we want to create our app. We execute Heroku create <name-of-your-app> in our example. We call the app fe-dart-server. If you do not pass a name, it will create a random app name for you.

1heroku create fe-dart-server
2Creating ⬢ fe-dart-server... done
3https://fe-dart-server.herokuapp.com/ | https://git.heroku.com/fe-dart-server.git

As a result, Heroku delivers us two URLs. The first one is the URL directly to our app. Currently, we do not have an application running on https://fe-dart-server.herokuapp.com/.Therefore, you will find the documentation link of Heroku if you open it. The second link is the internal git server of Heroku, from which it will use your source code to build the project. We will need to add a new remote to git to push our Dart project.

1# If you have not initialized your project with git
2git init
3git add remote heroku https://git.heroku.com/fe-dart-server.git

Hint: It could be that if your project was already in git, it was already added with the Heroku create command

Now that your app is registered to Heroku, we have to set up a buildpack.

How Heroku works

Now it is essential to know how Heroku works. A build pack is responsible for transforming your deployed source code into a slug, which can then be executed by a dyno. You can read more about how Heroku works here. So before we go deeper into the topic, let's quickly check what a slug and a dyno are.

A slug is a bundle of your source, fetched dependencies, the language runtime, and compiled/generated output of the build system - ready for execution.

Dynos are isolated, virtualized Unix containers that provide the environment required to run an application.

Source: devcenter.heroku.com

Set up a build pack for Dart

Unfortunately, Heroku is not yet supporting Dart with an official build pack. Therefore, we have to take advantage of the fantastic Dart & Flutter Community, which has created already a build pack that we can use. We will use in this tutorial the most starred build pack by igrigorik.

To use the build pack, we will have to tell Heroku to use a specific download URL for the Dart language and configure the build pack we want to use. To find a Dart SDK URL, we check the Dart Archive page. Then, we select Linux and the version we would like to install. This example case is version 2.16.2`, which is the current version. Now right, click on Dart SDK and copy the link address. We will need it in a second.

How to get a Dart download URL

Now it is time to set the Dart URL and our BUILDPACK_URL for our Heroku app by executing in our terminal.

1heroku config:set DART_SDK_URL=https://storage.googleapis.com/dart-archive/channels/stable/release/2.16.2/sdk/dartsdk-linux-x64-release.zip
2
3Setting DART_SDK_URL and restarting ⬢ fe-dart-server... done, v3
4DART_SDK_URL: https://storage.googleapis.com/dart-archive/channels/stable/release/2.16.2/sdk/dartsdk-linux-x64-release.zip
5
6heroku config:add BUILDPACK_URL=https://github.com/igrigorik/heroku-buildpack-dart.git
7
8Setting BUILDPACK_URL and restarting ⬢ fe-dart-server... done, v4
9BUILDPACK_URL: https://github.com/igrigorik/heroku-buildpack-dart.git

Now it is time to push our source code to Heroku by pushing our source code to the remote git that we got when we created our Heroku app.

1git add . # Adds all files to git in this repository
2git push --set-upstream heroku main # Sets the upstream branch to heroku main and pushes all files

If you are doing it in the terminal, Heroku will give you a lot of logging information about the build process.

1remote: -----> Discovering process types
2remote: Procfile declares types -> (none)
3remote:
4remote: -----> Compressing...
5remote: Done: 195.9M
6remote: -----> Launching...
7remote: Released v7
8remote: https://fe-dart-server.herokuapp.com/ deployed to Heroku
9remote:
10remote: Verifying deploy... done.
11To https://git.heroku.com/fe-dart-server.git
12 refs/heads/main:refs/heads/main 75c0e7f..b4f1198
13Done

The log above tells us that everything was successful, but one step is missing. First, we need to declare the dynos we want for our app. For that, we need to create a Procfile in the root directory of our project. Then, we enter the dyno and what it should start to execute our server. In our case, we execute the dart_server.dart in the bin folder.

Procfile
1web: ./dart-sdk/bin/dart bin/dart_server.dart

Hint: The Procfile does not have a file extension like .txt or .js.

If we now commit and push again to the Heroku git server we are ready to see our server in action.

1git commit -m "Added Procfile to setup the dyno"
2git push --set-upstream heroku main

🎉 Great, if everything worked well, you should have now your first running Dart Server on Heroku.

Troubleshooting

As always, some things could go wrong, and I try to add a collection that we found out during our live stream.

Dynamic Port

Heroku does not provide you static port, so you will get a new port every time the instance is started. Especially in the free plan, that happens pretty frequently and therefore, you must take the PORT provided by the Environment variables of Heroku.

1var env = Platform.environment;
2
3var port = env.entries.firstWhere((element) => element.key == 'PORT',
4 orElse: () => MapEntry('PORT', '8080'));
5
6var server = await shelf_io.serve(
7 logRequests().addHandler(router), '0.0.0.0', int.parse(port.value));

Replace localhost with 0.0.0.0

Heroku is pointing to itself while setup a server you will need to change localhost to 0.0.0.0

1var server = await shelf_io.serve(
2 logRequests().addHandler(router), '0.0.0.0', int.parse(port.value));

Wrapping up

Great, we did it. With these steps, we published our server to Heroku and made our very first deployment possible. The next milestone is to create a helpful app out of this server. We were maybe starting with a small quiz app that allows you and your friends to learn more about development. For that, you will probably need more insights into the shelf_router package or an even bigger solution like Conduit. Feel free to share your first examples with me on Twitter with the Hashtag #FlutterExplained. I cannot wait to see your results!