BlogHome
Deploy A Rust Website on Heroku

Deploy A Rust Website on Heroku

Mar 14, 2021Updated on Jan 7, 2022

Rust is a blazing fast and memory efficient programming language that's used by tech companies like Firefox, Dropbox and Cloudflare to name a few.

Today we are going to focus on the web side of Rust, hence the name "Rocket".

Well, per the official website rocket.rs - "Rocket is a web framework for Rust that makes it simple to write fast, secure web applications without sacrificing flexibility, usability, or type safety". That's a self explanatory introduction, nothing more I can add.

Having completed the formalities, let's launch some Rockets.

Setting up Rocket

To run Rocket locally we need to have installed a compatible version of Rust (install Rust), and since Rocket uses advanced and unstable features of Rust we'll need to use the nightly version of Rust. To configure the nightly version of Rust as the default toolchain run the following command on your terminal.

rustup default nightly

or you can set it as the default toolchain for your Rocket project only by running the following command inside the Rocket project's directory after having created it.

rustup override set nightly

Now, proceed with creating a new cargo project

Cargo new rocket-demo-app --bin

# switch into the project's directory
cd rocket-demo-app

Add Rocket as a dependency in the Cargo.toml file found on the project's root.

[dependencies]
rocket = "0.4.7"

Update the src/main.rs file by adding a bit of Rocket code

#![feature(proc_macro_hygiene, decl_macro)]

#[macro_use] extern crate rocket;

#[get("/")]
fn index() -> &'static str {
  "This is my Rocket Demo app"
}

fn main() {
  rocket::ignite().mount("/", routes![index]).launch();
}

Then run the following command,

Cargo run

Rust will fetch all the dependencies used by Rocket, make a dev build of our project and run the binary code, launching our project.

Finished dev [unoptimized + debuginfo] target(s) in 3m 00s
     Running `target\debug\rocket-demo-app.exe`
🔧 Configured for development.
    => address: localhost
    => port: 8000
    => log: normal
    => workers: 8
    => secret key: generated
    => limits: forms = 32KiB
    => keep-alive: 5s
    => read timeout: 5s
    => write timeout: 5s
    => tls: disabled
🛰   Mounting /:
    => GET / (index)
🚀 Rocket has launched from http://localhost:8000

In the output above, Rocket has launched our project on the 8000 port, so to view it navigate to http://localhost:8000.

All we did on the main/src.rs file is declare an index route, mount it at the "/" path and launch our rocket app.

Rocket routes

Rocket applications center around routes and handlers, where a Rocket route is simply a combination of parameters matching an incoming request and a handler that processes the request and returns a response.

A route is declared by annotating a function just as in the example above, the index route is:

#[get("/")]
fn index() -> &'static str {
  "This is my Rocket Demo app"
}

Where the annotation at the top - #[get("/")] is the route's attribute and the function that follows below it fn index() is the route's handler.

Route mounting

Let's add a new route to our Rocket project. Add the following code after the index route.

#[get("/about")]
fn about() -> &'static str {
  "This is the about page of my Rocket Demo app"
}

And re-run the cargo project.

When you try navigating to the /about page, you'll see a 404: Not Found error.

What happened?

Well, Rocket needs to mount routes before dispatching requests to them, that is the reason we have rocket::ignite().mount("/", routes![index]).launch(); inside the main() function for the first route. Let's mount our _about page route too. Update the main() function with the following code.

fn main(){
  rocket::ignite().mount("/", routes![index, about]).launch();
}

Re-run cargo and try visiting the "/about" route again.

After declaring and mounting our routes, we call the lauch() method which starts up the server and has our Rocket app up and running waiting for incoming requests to dispatch them accordingly.

For more on Rocket requests head to the official documentation

Before proceeding with the next step, use git to stage and commit all the changes done to the app.

git add . && git commit -m "initialize Rocket project"

Setting up Heroku

Start with creating an account on Heroku if you do not have one before proceeding.

Inside the Heroku dashboard add a new app and fill in it's details Add new Heroku app

Next, download and install the Heroku CLI, then proceed with running the following command inside the project's directory.

heroku login

Follow the instructions which will redirect you to your browser and let you log into your Heroku account.

Back on the project, link the remote Heroku app to your Rocket project with the following command.

heroku git:remote -a rocket-demo-app

Create a new file on the project's root and name it Procfile without any extensions, add the following code into it.

web: ROCKET_PORT=$PORT ROCKET_KEEP_ALIVE=0 ./target/release/rocket-demo-app

Specify a nightly version of Rust to work with by creating another file on the project's root, naming it rust-toolchain (without a file extension). The following nightly version is a good start:

nightly-2020-10-24

Commit the new changes.

Use Heroku's Rust buildpack.

heroku buildpacks:set emk/rust

Then push the changes to heroku.

git push heroku master

After finishing all it needs to do, the command-line tool will give you the link your app has been deployed to, open the link and view the deployed app.

remote: -----> Building application using Cargo
remote:    Compiling rocket-demo v0.1.0 (/tmp/build_898d5ac6)
remote:     Finished release [optimized] target(s) in 3.39s
remote: -----> Discovering process types
remote:        Procfile declares types -> web
remote:
remote: -----> Compressing...
remote:        Done: 1.5M
remote: -----> Launching...
remote:        Released v6
remote:        https://rocket-demo-app.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/rocket-demo-app.git
   13450ef..0febf7c  main -> main

Above is an example output you'd expect from the heroku-cli tool.

This is a nice start when delving into deploying Rust applications and in this particular case we were deploying a Rocket framework app on Heroku.

There is so much more to learn and experiment in this "fast, easy, and flexible" framework, this has just been a short intro into deploying it, more can be learnt here.

Go out there and launch some Rockets.