Digital Ocean App Platform Hackathon: Using Non Natively Supported Platforms (Rust + Rocket)
Davide Del Papa
Posted on December 14, 2020
[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.
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)
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>
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
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
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
Now we can add dependencies from the command line (and from make, shell scripts, Dockerfile, etc):
cargo add rocket
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();
}
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
The above implies a current version of docker installed in your system. If not, please follow the instructions below:
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 .
(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
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>
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).
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"
Then you can push to main
(the master
replacement).
git push origin main
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"
.
We go at the end of the list and select the Deploy a GitHub Repo
. This will prompt the Apps 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.
Then you will be prompted with the options for the name, the branch and the region of deployment
Then you will be asked some configuration info: since there's a Dockerfile
it will automatically detect everything.
Then you have to select your plan: the starter (free) plan is only for static sites, so it is unavailable.
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.
Now you can launch your app (Launch Basic App
button, bottom right).
At the end of the procedure you will get a success banner with a link to the Live App
Yatta! We made it!
You can check the echo route as well:
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!):
- Visit the Apps control panel at https://cloud.digitalocean.com/apps
- Navigate to the do-apps-rust-example app
- Choose "Settings"->"Destroy"
- 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!
Posted on December 14, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
December 14, 2020