DEV Community

Cover image for Digital Ocean App Platform Hackathon: Using Non Natively Supported Platforms (Rust + Rocket)
Davide Del Papa
Davide Del Papa

Posted on • Edited on

Digital Ocean App Platform Hackathon: Using Non Natively Supported Platforms (Rust + Rocket)

[Photo by Marco Bianchetti on Unsplash, modified (cropped)]

DISCLAIMER: The following might require you to spend some money on the DigitalOcean platform.

However, in the repo and here, I have set up a Deploy to DigitalOcean button that lets you try the finished app, and guides you to registration on DigitalOcean, if you did not register yet, and gives you some money buffer for 60 days to try DigitalOcean's products.

The button has a referral code as well, so tht you can have a money buffer to try DO products, and I can have some coffee (I hope). Yet you are free to try all this without touching that button; you just need to subscribe to Digital Ocean (but you won't get any trial money buffer in that case).

Introduction

The new Digital Ocean App Platform Dev.to Hackathon has just started. However, while there is a big amount of documentation (and growing) out there, on how to start to use this wonderful new tool, much is lacking if you want to use unsupported languages.

Therefore this tutorial is trying to fill in the gap, providing a gentle introduction on how to deploy not natively supported apps.

Plan of Action

Digital Ocean does support a lot of programming languages, but still, it does not as yet provide support for interfacing any chosen language. So, how would we go about and deploy an unsupported language nevertheless?

Well, Digital Ocean's App Platform supports Docker: this will be our way to "smuggle in" an unsupported language, let's say, Rust.

The plan is this: we will fork Digital Ocean's docker repository, then personalize it, and finally deploy it.

How to Follow the Tutorial Even Without Installing Rust

The following implies that you have on your system a valid Rust installation (More info here, the official Rust installation page).

However, it is not needed that you have Rust installed on your system. If you don't want to install Rust, bust still you want to use it, just use my repo as a template (green button top, near the cloning URLs), instead of forking Digital Ocean's docker repository.

Then start to follow from the section called Try Locally the App.

In fact, we will use Rust inside an image to compile the app.

Notes: you must have however a working Docker installation on your system to follow this tutorial. That is needed to check the installation

Fork and Make It Your Own

Go to: github.com/digitalocean/sample-dockerfile

Fork the repo

Fork the repo.

Fork done

Now you need to go to your forked version (GitHub automatically redirects to it, once the forking process is completed) and rename the repo (under the Setting tab)

rename the repo

It is now time to clone the repository on your machine. Go to the shell:

git clone https://github.com/<your-account-name>/<your-project-name>.git
cd <your-project-name>
Enter fullscreen mode Exit fullscreen mode

Now we need to create a Rust project (you can get rid of the two GO files, namely go.mod and main.go if you want).

Simple Rust App

On the shell, inside the repository root, give the following command:

cargo init --name myapp
Enter fullscreen mode Exit fullscreen mode

Now we have a Cargo.toml file and a src/ folder (plus a .gitignore file).

We should also set the nightly toolchain:

rustup override set nightly
Enter fullscreen mode Exit fullscreen mode

There we go, we are ready to develop a Rocket app.

If you do not have it installed, I recommend a little, useful tool: cargo edit; with it we can even script most of the setup for a new cargo project. To install it, just run:

cargo install cargo-edit
Enter fullscreen mode Exit fullscreen mode

Now we can add dependencies from the command line (and from make, shell scripts, Dockerfile, etc):

cargo add rocket
Enter fullscreen mode Exit fullscreen mode

Let's change now the main.rs file inside src/

src/main.rs

Change the content of src/main.rs to match the following:

#![feature(proc_macro_hygiene, decl_macro)]
use rocket::*;
use rocket::response::content::Html;

#[get("/echo/<echo>")]
fn echo_fn(echo: String) -> String {
    format!("{}", echo)
}

#[get("/")]
fn hello_fn() -> Html<String> {
    Html("<h1>Hello, world!</h1><p>From inside a DigitalOcean App</p>".into())
}

fn main() {
    rocket::ignite().mount("/", routes![echo_fn, hello_fn]).launch();
}
Enter fullscreen mode Exit fullscreen mode

In the above we created two routes, a echo route, that re-prints everything is passed to it after a slash /, and a hello route, that greets with the usual hello, world. This last is placed as the root of the server.

The Dockerfile

Now we usually would compile and run the above with a cargo run (and you can still give it a try, to make sure there were not errors in the code).
However, this time we have to make sure we are able to do it from inside a docker container.

We need to change the Dockerfile of the project. It must look like the following:

FROM rust:1.40 as builder
WORKDIR /usr/src/myapp
COPY . .
RUN rustup override set nightly; \
    cargo install --path .

FROM debian:buster-slim
COPY --from=builder /usr/local/cargo/bin/myapp /usr/local/bin/myapp
ENV ROCKET_PORT 8080
CMD myapp
Enter fullscreen mode Exit fullscreen mode

The above implies a current version of docker installed in your system. If not, please follow the instructions below:

docs.docker.com/get-docker/

There you can find instructions for various operating systems.

Try the App Locally

Before deploying to Digital Ocean, let's build this on our machine:

docker build --tag myapp .
Enter fullscreen mode Exit fullscreen mode

(take care there's a dot at the end of the above command!)

Then, we can run it with:

docker run --rm --network="host" -id myapp
Enter fullscreen mode Exit fullscreen mode

The above should give you a hash that represents the running container. Keep it for later, because to halt the container after use, you may run:

docker kill <container-id>
Enter fullscreen mode Exit fullscreen mode

Still if you forgot, you can get the id (a shorter yet usable one) with docker ps.

To test the container while running, point your browser to localhost:8080 (with the --network="host" we connected the docker's own localhost with the host machine's one).

Our app running

When we are satisfied we can shut down the image (docker kill) and go to the next step.

Deploying our image to DigitalOcean's App Platform

First we have to commit our repo to GitHub:

git add -A 
git commit -m "First Rust Commit"
Enter fullscreen mode Exit fullscreen mode

Then you can push to main (the master replacement).

git push origin main
Enter fullscreen mode Exit fullscreen mode

Now we can go to DigitalOcean's App page.

If you did not register as yet, you have to do so before this step.

Small Ad Note: You might use the Deploy on DigitalOcean button on my repo, that lets you try the final app and gets you a credit for 60 days to get you some $ to try the app without spending any $ (DISCLAIMER: It has a referral code so while you get the free credit for 60 days as trial period I should get something as well, qui pro quo I suppose).

If we do not have any deployment so far we are greeted with an action button: "Let's build something".

Deploy GitHub Repo

We go at the end of the list and select the Deploy a GitHub Repo. This will prompt the Apps Panel.

App panel

Clicking on the Launch Your App button will start the procedure to allow DigitalOcean to Link Your GitHub Account if it is the first time. Just follow the procedure.

At the end of the procedure, the page will ask you to select a repository.

Select a Repo

Then you will be prompted with the options for the name, the branch and the region of deployment

App Options

Then you will be asked some configuration info: since there's a Dockerfile it will automatically detect everything.

App Configuration Options

Then you have to select your plan: the starter (free) plan is only for static sites, so it is unavailable.

Select a Plan

However, make sure at the bottom of the page to select the 512 MB RAM, 1 CPU container, that is the 5$/Month option (not selected by default). This will take some more build times (to me it took a good 12 minutes), but it still works.

Select Cheapest Plan

Now you can launch your app (Launch Basic App button, bottom right).

Build the App

At the end of the procedure you will get a success banner with a link to the Live App

Success Banner

Yatta! We made it!

Live Running App

You can check the echo route as well:

Live Running App: Echo Route

Everything works like a charm.

Quick Troubleshot

It might happen (to me it did) that Digital Ocean gives some random error at the very first attempt, and the build fails.

Since the app is rebuild after each commit, even changing a little thing in the README.md will trigger a new build; so, you can change some unimportant thing, commit, and the build will restart. If it fails again, then probably the error is more serious, or maybe there's a bug or a typo somewhere in the code, and you should take action.

In this case consider cloning my repo altogether, and try deploying it (or use the Deploy to DigitalOcean button).

Deleting the App

When you finish to try it and make some changes, if you do not need it anymore, you can delete the app by following these steps (the following is taken from DigitalOcean's own repo, so I guess it is important!):

  1. Visit the Apps control panel at https://cloud.digitalocean.com/apps
  2. Navigate to the do-apps-rust-example app
  3. Choose "Settings"->"Destroy"
  4. A confirmation message will be prompted, where you have to re-insert the name of the app (to make sure it was not done by mistake)

This will delete the app and destroy any underlying DigitalOcean resources

Note: If you don't delete your app, charges for the use of DigitalOcean services will continue to accrue.

Conclusions

We have seen how to deploy non natively supported languages (Rust in this case) to DigitalOcean's App Platform, by using the supported Docker images.

Now you can participate to the Digital Ocean App Platform Dev.to Hackathon also using Rust.

If you want to set up an API with Rust, I am currently holding a series on Rocket, and the first tutorials deal with the API world. It covers the basics, integration with MongoDB or Redis, and more is coming.

Stay healthy, stay tuned!

Top comments (0)