Hosting an R Plumber API using Azure App Service

Veerle van Leemput
8 min readAug 31, 2021

Turn your R code into an API and host it to enable worldwide access

Introduction

In todays world, web services are heavily used to allow systems to interact with one another. R is one of my favourite programming languages and it’s especially good at data processing, modeling, and visualisation. But you can do a lot more with R too: building apps, interactive reports and… building web services! One way to share your R code with the world is by transforming your R code into a web service. The plumber R package is the tool to do that: it allows us to expose R code as a service available to any other service on the web.

While developing an R plumber web service (aka API) is straightforward, there are various ways to host an API. There is no one correct way to do it, most often the choice depends on your existing infrastructure and your specific use case. In this article I’ll guide you through the steps to host a very basic Plumber API using Azure App Service.

Prerequisites

To follow along with this guide you’ll need the following:

  • You need an Azure subscription to set up the required services.
  • You are able to access the Azure Command Line Interface (CLI).
  • Docker is (or can be) installed on your local machine or the server you’re intending to build the image from.
  • To execute certain commands, you need sudo or admin rights.

Project overview

We need a couple of files to make everything work:

plumber-to-azure-demo 
|__ Dockerfile
|__ execute_plumber.R
|__ plumber.R

All these files are available in this repo on GitHub.

Creating a simple R Plumber API

Let’s start with creating a simple API using the Plumber package. Plumber allows you to create APIs by decorating existing R code with special annotations that start with #* . The example below shows a file named plumber.R and is a copy from the file being used throughout the plumber documentation.

# plumber.R# libraries 
library(plumber)
#* Echo back the input
#* @param msg The message to echo
#* @get /echo
function(msg="") {
list(msg = paste0("The message is: '", msg, "'"))
}
#* Plot a histogram
#* @serializer png
#* @get /plot
function() {
rand <- rnorm(100) hist(rand)
}
#* Return the sum of two numbers
#* @param a The first number to add
#* @param b The second number to add
#* @post /sum
function(a, b) {
as.numeric(a) + as.numeric(b)
}

In the example above, we have three endpoints: two that serve GET requests, and one that serves a POST request. We’re not going into the difference between GET, POST and other type of requests, but if you want to find out more I recommend looking at this overview.

In the same folder, we also create a script named execute_plumber.R. This script will be used in the Dockerfile to launch the API at a later stage.

# execute_plumber.R# Execute plumber 
plumber::plumb(file='plumber.R')$run(host = '0.0.0.0', port = 8080)

Note that the host we specify (0.0.0.0) enables traffic from the outside. If we don't do this, it defaults to port 127.0.0.0- and that is reserved for IP traffic local to your host. The port we specified, 8080, is the same as we will later use in our Dockerfile. It’s not a requirement to use this specific port, you can use others as well. As long as they match.

You can check if everything works by simply executing the execute_plumber.R file on your machine.

Setting up Azure Container Registry

The first step towards hosting our API is to create an Azure Container Registry to store our Docker image in. A Docker image is essentially a package of software that includes everything needed to run an application. It makes sure you have a consistent way of running your software. Azure Container Registry (ACR) is a private registry service for building, storing, and managing container images and other related artifacts. To set up ACR, go to the Azure Portal, login and create a new Container Registry:

Once there, fill in all the required information. If you don’t have a resource group yet, you need to create one.

Click ‘review + create’. When deployment of the resource is finished you can visit your resource:

The next thing you want to do is to enable the admin user. You can do that at ‘Access keys’ under ‘Settings’. This allows you to publish a Docker image to the registry from the Azure Command Line Interface at a later stage.

Once you’ve set up ACR, you can start creating, building and pushing an image to it.

Creating, building and pushing a Docker image

If you want to create a Docker image, you need Docker. I installed Docker on Ubuntu 18.04 via the command line using:

sudo apt install docker.io

If you’re on another platform you can take a look here for installation instructions.

The installation succeeded if you run docker —-version in the terminal and it returns something like Docker version 20.10.7, build 20.10.7-0ubuntu1~18.04.1 .

Once Docker is installed we can create a Dockerfile. A Dockerfile is a text file that contains all the commands a user calls on the command line to assemble an image. The broad thing we want to do is: install R, install necessary dependencies, and run our API.

To install R we can use an existing Docker image. We will use the Debian Linux based rocker/r-base Docker image from the Rocker project.

Call the text file ‘Dockerfile’ and place the following content in it:

# DockerfileFROM rocker/r-base:4.0.3 # install the linux libraries needed for plumber 
RUN apt-get update -qq && apt-get install -y \
libssl-dev \
libcurl4-gnutls-dev \
libsodium-dev
# create the application folder
RUN mkdir -p ~/application
# copy everything from the current directory into the container
COPY "/" "application/"
WORKDIR "application/"
# open port 8080 to traffic
EXPOSE 8080
# install plumber
RUN R -e "install.packages('plumber')"
# when the container starts, start the main R script ENTRYPOINT ["Rscript", "execute_plumber.R"]

We’re going to build and deploy the Dockerfile to ACR using the Azure Command Line Interface (CLI). If you don’t have it yet you can easily install it by running:

curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash

Note that this is for Ubuntu. Installation instructions for different operating systems can be found here.

To verify, login to Azure CLI using:

az login

If you’re working on a headless server, you need to open the browser page at https://aka.ms/devicelogin and enter the authorization code displayed in your terminal. Once that’s working you can move on with login into the registry.

The general command to login to the registry is:

sudo az acr login —-name <registry-name>

In our case that is:

sudo az acr login --name plumberdemo

You’ll get a message saying ‘Login Succeeded’ when you were succesful.

Now cd into the directory of your Dockerfile:

cd /path/to/plumber-to-azure-demo

And use the following command to build and upload the Dockerfile:

sudo az acr build --image plumberdemoimage:v1 --registry plumberdemo --file Dockerfile .

This will take a bit of time since it’s installing all the necessary things. When it’s done, we can check if the image is in our Repositories:

Using Azure App Service to host your Plumber API

After finishing pushing the image to your container registry, we can deploy the image to Azure App Service.

Azure App Service enables you to build and host web apps and web services in any programming language without managing infrastructure. It offers features like auto-scaling and high availability, supports Linux and Windows, and enables automated deployments from any Git repo. Azure App Services offers standard runtime stacks like Node, Java, Ruby or .NET, but you can also use a custom Docker image to run your web app on an application stack that is not already defined in Azure. Just like we’re going to do.

First you need to create a new Web App resource:

Fill in the required details and pick ‘Docker container’ as publishing choice. You’ll need an App Service Plan to add your Web App to.

The next step is the Docker configuration:

The images will be automatically retrieved once you select your registry. Click ‘review + create’ and wait for deployment to be finished.

And that’s it! You’re now able to access your R Plumber API via your browser, Postman, or your terminal:

Note that you won’t be able to access this actual URL- IP access restrictions were added
Note that you won’t be able to access this actual URL- IP access restrictions were added

Next steps

There are many more things we can do now we have hosted our API with Azure App Service.

One of those things is setting up GitHub Actions so we can enable continuous deployment for our API: as soon as something on a specified branch changes we can let the Dockerfile rebuild itself in order to provide users with the latest changes.

Another thing is that our API is now exposed to the world. After putting together this demo I set IP restrictions on the App Service. That’s one thing you can do. But normally you want to add some authentication to it. For example, we could use Azure API Management to achieve that.

These and other next steps will be tackled in next articles.

--

--

Veerle van Leemput

🚀 Entrepreneur and Data Scientist who gets excited about data and programming | Vue, Node.js, R, Shiny, Azure