How to deploy a Rust REST API application on AWS with ease

In this article, you will learn how to deploy a Rust REST API application on AWS with ease

Fast, reliable, productive - Pick three | Rust's slogan

Rust is a systems programming language that runs blazingly fast, prevents segfaults, and guarantees thread safety.

In this article, you will learn how to deploy a Rust API easily in a few steps. This article is separate into two parts:

  • Create a Rust REST API app
  • Dockerized our Rust REST API app
  • Deploy our Rust REST API app on AWS

Let's go!

Create a Rust REST API app

To illustrate the deployment of our Rust API application, we are going to create an API to know if a number is prime number. Let's create our Rust project using cargo

create our rust project
cargo new --bin rust-prime-number-api

Now you must have a rust-prime-number-api folder with 2 files:

  • Cargo.toml
  • src/main.rs

To build our Rust REST API we are going to use Rocket - a web framework for Rust that makes it simple to write fast web application.

Add the rocket and serde (JSON serializer/deserializer) dependencies to your Cargo.toml, then run cargo fetch (optional) to update your local dependencies.

Cargo.toml
[package]
name = "rust-prime-number-api"
version = "0.1.0"
authors = ["Romaric Philogene <[email protected]>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rocket = { version = "0.5.0-rc.1", features = ["json"] }
serde = { version = "1.0.130", features = ["derive"] }
serde_json = "1.0.68"

Put inside your src/main.rs the following Rust code

src/main.rs
#[macro_use]
extern crate rocket;
use rocket::serde::json::Json;
use serde::Serialize;
use std::time::SystemTime;
use std::net::{IpAddr, Ipv4Addr};
#[derive(Serialize)]
struct NumberResponse {
number: u64,
is_prime_number: bool,
execution_time_in_micros: u128
}
#[get("/")]
fn index() -> &'static str {
"This is my Rust prime number REST API"
}
#[get("/isPrime?<number>")]
fn get_is_prime(number: u64) -> Json<NumberResponse> {
let now = SystemTime::now();
Json(NumberResponse {
number,
is_prime_number: is_prime(number),
execution_time_in_micros: now.elapsed().unwrap().as_micros(),
})
}
fn is_prime(n: u64) -> bool {
if n <= 1 {
return false;
}
for a in 2..n {
if n % a == 0 {
return false;
}
}
true
}
#[rocket::main]
async fn main() {
let mut config = rocket::config::Config::default();
config.address = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0));
let _ = rocket::build()
.configure(config)
.mount("/", routes![index, get_is_prime])
.launch()
.await;
}

Run cargo run and you are supposed to get the following output

🔧 Configured for debug.
>> address: 0.0.0.0
>> port: 8000
>> workers: 16
>> ident: Rocket
>> keep-alive: 5s
>> limits: bytes = 8KiB, data-form = 2MiB, file = 1MiB, form = 32KiB, json = 1MiB, msgpack = 1MiB, string = 8KiB
>> tls: disabled
>> temp dir: /var/folders/td/bjr48yg96gd2xgd3s44fg40c0000gn/T/
>> log level: normal
>> cli colors: true
>> shutdown: ctrlc = true, force = true, signals = [SIGTERM], grace = 2s, mercy = 3s
🛰 Routes:
>> (index) GET /
>> (get_is_prime) GET /isPrime?<number>
📡 Fairings:
>> Shield (liftoff, response, singleton)
🛡️ Shield:
>> X-Frame-Options: SAMEORIGIN
>> Permissions-Policy: interest-cohort=()
>> X-Content-Type-Options: nosniff
🚀 Rocket has launched from http://127.0.0.1:8000

You can try your Rust REST API by opening http://127.0.0.1:8000/isPrime?number=9293029022983991 in your browser.

{
"number": 9293029022983992,
"is_prime_number": false,
"execution_time_in_micros": 942894
}

Let's now containerized our app with Docker to deploy it on our AWS account.

Dockerized our Rust REST API app

To run our Rust app we need to provide a valid Dockerfile. If you are not familiar with Docker, you can take a look to this article. Here is the content of our Dockerfile.

Dockerfile
####################################################################################################
## Builder
####################################################################################################
FROM rust:latest AS builder
RUN rustup target add x86_64-unknown-linux-musl
RUN apt update && apt install -y musl-tools musl-dev
RUN update-ca-certificates
# Create appuser
ENV USER=app
ENV UID=10001
RUN adduser \
--disabled-password \
--gecos "" \
--home "/nonexistent" \
--shell "/sbin/nologin" \
--no-create-home \
--uid "${UID}" \
"${USER}"
WORKDIR /app
COPY ./ .
RUN cargo build --target x86_64-unknown-linux-musl --release
####################################################################################################
## Final image
####################################################################################################
FROM scratch
# Import from builder.
COPY --from=builder /etc/passwd /etc/passwd
COPY --from=builder /etc/group /etc/group
WORKDIR /app
# Copy our build
COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/rust-prime-number-api ./
# Use an unprivileged user.
USER app:app
CMD ["/app/rust-prime-number-api"]

Deploy our Rust REST API app on AWS

To deploy our Rust app on AWS we are going to use Qovery. Qovery is the simplest way to deploy any app on AWS. It is the perfect candidate to deploy our Rust REST API in a few steps.

Sign up into Qovery

First, you need to sign up or sign in on Qovery.

  • Sign in to the Qovery web interface.

    Qovery Sign-up page

  • Connect your AWS account

    To connect your AWS account check out this guide.

    Deploy our Rust REST API app

    Once your AWS account is set-up, you can deploy your Rust app by..

    Creating a project prime number.

    Create a project

    Creating an environment prod.

    Create an environment

    Creating an app by selecting your Rust app repository, build mode > Dockerfile, and the port 8000.

    Create an app

    And deploy! That's it 🔥... nothing more. Our Rust REST API app is ready

    Our app is deployed

    Check out this video to see how I quickly deploy my Rust REST API with Qovery.

    Watch this video showing the final result 👇

    Wrapping up

    Rust combined to Rocket web framework turns building REST API super easy. Deploying your Rust app on AWS with Qovery is as simple as selecting your GitHub repository. Nothing more. Hope you liked it.

    Useful resources

    Tutorial