Deploy a Rust App

Rust (opens in a new tab) is a high-performance language designed to make it easier to write reliable, memory safe applications by default. It is often used for systems programming as a safer alternative to C and has seen wide adoption by teams building native applications in many contexts.

This guide explains how to deploy a Rust application to Koyeb using Git-driven deployment. The application will be packaged using a Dockerfile and can be deployed straight from a GitHub repository or from a pre-built image in container registry.

To successfully follow this documentation, you will need to have a Koyeb account (opens in a new tab). You can optionally install the Koyeb CLI if you prefer to follow this guide without leaving the terminal.

You can deploy and preview the Rust application from this guide using the Deploy to Koyeb button below.

Deploy to Koyeb (opens in a new tab)

You can consult the repository on GitHub (opens in a new tab) to find out more about the example application that this guide uses.

Create the Rust app

To create a minimal Rust application, you'll need to install Rust (opens in a new tab) and cargo, the language's package manager on your local system.

Initialize the project structure

Once these tools are available, initialize a new project and move into the project directory by typing:

cargo new example-rust
cd example-rust

The command above initializes the project directory with the following assets:

  • Cargo.toml: Defines and manages the project's metadata and dependencies.
  • src/main.rs: The directory for the source code and an initial "Hello world" program file.
  • .git/: A Git repository for version control.
  • .gitignore: A default ignore file to omit build artifacts from version control.

Test the default application

You can compile and run the example application by typing the following in the project directory:

cargo run

The cargo command will build the project and run the program, producing a "Hello, world!" message. It will place the compiled binary and related file into a directory structure in a new target directory. By default, the assets will be stored in target/debug/ since this is an unoptimized build with debugging features enabled.

Add dependencies and create a web application

While the generated application can produce output in the terminal, we'll install additional dependencies to serve responses over the web.

Open the Cargo.toml file in your text editor and add the Actix Web framework (opens in a new tab) to your dependencies:

Cargo.toml
[package]
name = "example-rust"
version = "0.1.0"
edition = "2021"
 
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
[dependencies]
actix-web = "4"

Cargo will automatically install Actix and its dependencies the next time the project is built.

Next, open the src/main.rs file in your editor and replace the contents with the following:

src/main.rs
use std::env;
use actix_web::{get, App, HttpResponse, HttpServer, Responder};
 
#[get("/")]
async fn hello() -> impl Responder {
    HttpResponse::Ok().body("Hello world!")
}
 
#[actix_web::main]
async fn main() -> std::io::Result<()> {
 
    let port: u16 = env::var("PORT")
        .unwrap_or("8000".to_string())
        .parse()
        .unwrap();
 
    HttpServer::new(|| {
        App::new()
            .service(hello)
    })
    .bind(("0.0.0.0", port))?
        .run()
        .await
}

This is still a "hello world" application, but this time, served over HTTP using Actix.

The file starts with a few use statements to access items from the Actix module and environment variable functionality from the standard library. Afterwards, it defines a hello() function that will respond to requests on the root path (/) with "Hello world!".

The main function configures the Actix web server to serve that function. It checks for a PORT environment variable to determine which port to listen on and sets the fallback value to 8000.

Test the web application

Build and run the application again to ensure that our changes compile cleanly and work as expected:

cargo run

After downloading the project's new dependencies, the application will be built and run. If you visit localhost:8000 in your browser, you should see a "Hello world!" message.

Press CTRL-C to stop the server when you are finished.

Test the port configuration by running the application again with a custom port:

PORT=5555 cargo run

The application should now be served at localhost:5555 instead.

Create a Dockerfile for the project

To deploy our Rust application, we'll need to build and package it in a container. This can be done ahead of time and uploaded to a container registry like Docker Hub (opens in a new tab) or it can be done at the time of deployment using Koyeb's Dockerfile build process.

Start by creating a .dockerignore file in your main project directory. Inside, paste the following contents:

.dockerignore
target
.dockerignore
Dockerfile
.git
.gitignore

This tells the Docker build process to not copy the target directory or any Docker- or Git-related files to the container image.

Next, create a Dockerfile in the project root with the following contents:

Dockerfile
# Build stage
FROM rust:bookworm AS builder
 
WORKDIR /app
COPY . .
RUN cargo build --release
 
# Final run stage
FROM debian:bookworm-slim AS runner
 
WORKDIR /app
COPY --from=builder /app/target/release/example-rust /app/example-rust
CMD ["/app/example-rust"]

This Dockerfile uses a multistage build (opens in a new tab) to separate the build steps from the final image environment. This creates a more streamlined image and allows us to tightly control what files are included in the final image.

Both stages are based on Debian Bookworm containers. The first stage uses the Debian Bookworm Rust image to copy the application code and compile it into a production binary. This binary is copied over to the second stage, where the application is run in a more minimal environment.

If you have Docker installed locally, you can build and test the image on your computer and optionally upload it to a registry. You can deploy container images from any container registry to Koyeb.

We can also build the Dockerfile directly from the repository when we deploy, which is useful as a way of automatically deploying when changes occur. We will demonstrate this method as one of the options in this guide.

Push the project to GitHub

Once you're finished configuring the project locally, you can commit your work and push it to GitHub.

Rust automatically initialized a Git repository when the cargo new command was run, so we just need to add our changes to it. Run the following commands within the project's root directory to commit the project files and push changes to GitHub.

Remember to replace the values of <YOUR_GITHUB_USERNAME> and <YOUR_REPOSITORY_NAME> with your own information:

git add :/
git commit -m "Add project files"
git remote add origin git@github.com:<YOUR_GITHUB_USERNAME>/<YOUR_REPOSITORY_NAME>.git
git push -u origin main

Deploy to Koyeb using git-driven deployment

Once the repository is pushed to GitHub, you can deploy the Rust application to Koyeb. Any changes in the deployed branch of your codebase will automatically trigger a redeploy on Koyeb, ensuring that your application is always up-to-date.

To deploy the Rust app on Koyeb using the control panel (opens in a new tab), follow the steps below:

  1. Click Create Web Service on the Overview tab of the Koyeb control panel.
  2. Select GitHub as the deployment option.
  3. Choose the GitHub repository and branch containing your application code. Alternatively, you can enter our public Rust example repository (opens in a new tab) into the Public GitHub repository at the bottom of the page: https://github.com/koyeb/example-rust
  4. In the Builder section, choose Dockerfile.
  5. Name the App and Service, for example example-rust.
  6. Click the Deploy button.

A Koyeb App and Service will be created. Your application will be built and deployed to Koyeb. Once the build has finished, you will be able to access your application running on Koyeb by clicking the URL ending with .koyeb.app.

Deploy to Koyeb from a container registry

If you chose to upload your pre-built container image to a container registry, you can deploy the application from there instead of from GitHub.

To deploy a pre-built Rust container image on Koyeb using the control panel (opens in a new tab), follow the steps below:

  1. Click Create Web Service on the Overview tab of the Koyeb control panel.
  2. Select Docker as the deployment option.
  3. Choose the container image and tag from your registry and click Next to continue.
  4. Name the App and Service, for example example-rust.
  5. Click the Deploy button.

A Koyeb App and Service will be created. The container image will be pulled from the container registry and a container will be deployed from it. Once the initialization is complete, you will be able to access your application running on Koyeb by clicking the URL ending with .koyeb.app.