Rex Animal Health is a startup based in San Francisco, CA, that is seeking to transform the animal health and agriculture industries with a suite of innovative data-driven tools that track and analyze animal disease. I met up with Rex CEO Amado Guloy in San Francisco during a two-day hackfest hosted by Microsoft. Fellow Microsoft developer evangelist Tim Reilly and I worked with Amado to investigate how moving to Azure could improve his team’s workflow for developing, deploying, and hosting web applications built on Python and Angular.

Development team:

  • Amado Guloy – CEO, Rex
  • Tim Reilly – Technical Evangelist, Microsoft
  • Rachel Weil – Technical Evangelist, Microsoft

Customer profile

Rex is building a suite of tools that analyze and visualize data related to disease transmission, pathogenesis, and biosecurity in the global food supply. Rex combines clinical information from animal health records with genomic data to provide actionable insights about how genes are affected by human practices, common pathogens, and the environment.

rexanimalhealth.com

Problem statement

Amado was interested in adding Microsoft’s Power BI and Azure Machine Learning integration with his company’s web applications but wasn’t familiar with the Azure ecosystem. He wanted to get some experience with Microsoft offerings and was curious about how Azure cloud hosting compared to his current provider, Amazon Web Services (AWS). Tim and I worked with Amado to scope out a small proof-of-concept project that would help get Amado up and running with Azure and help him understand the benefits it might offer his startup.

Each of Rex’s handful of in-development analytics web applications was developed in two parts and split across two Linux virtual machines on AWS. One virtual machine hosted a genomics application written in Python; the second virtual machine ran a node and served an Angular web front end that brokered interactions between the user and the back-end application.

Having the two parts of the application on separate virtual machines allowed for the installation of specific system dependencies and facilitated development taking place at different times by different developers working in different programming languages. However, it also posed challenges. In this workflow, for example, the developer was responsible for managing not only the two application code bases but also collaborative deployment, an HTTP server on the virtual machine for the Angular application, and the two virtual machines themselves.

Solution

After reviewing Rex’s application infrastructure and comparing different Azure offerings and options, the team decided to take on the following steps for one of Rex’s web applications:

  1. Migrate the web front end from its existing Linux virtual machine to a web app using the Web Apps feature of Azure App Service.
  2. Migrate the Python back end from its existing Linux virtual machine to an Azure-hosted virtual machine.
  3. Discover and implement improvements to the development and deployment cycle.

Moving from a virtual machine-hosted website to Web Apps

Traditional cloud-hosted virtual machines on AWS and Azure are considered infrastructure as a service (IaaS) offerings. The server and storage infrastructure are provided—you guessed it!—as a service! However, the developer is still responsible for managing the virtual machine and its necessary dependencies and middleware. Rex’s applications were built on two traditional virtual machines, shown in the following diagram.

Two VMs (IaaS)

In the case of the Rex web front end, the virtual machine contained not only the Angular web application but also the web server and scripts needed to initiate prerequisite tasks. Node, Gulp, and Gulp plug-ins were used to serve the Angular app from the virtual machine.

Web apps are unique in that they are not IaaS but PaaS, or “platform as a service.” Azure’s PaaS offerings simplify the deployment of web apps by managing not just infrastructure but also much of the development tooling, middleware, OS updates, and so on, allowing developers to focus on the code they really care about. The following sketch shows Rex’s web app infrastructure under the Web Apps model.

One VM (IaaS) + one Azure web app PaaS)

As you can see, the Python back end remains on an IaaS-style virtual machine; the only difference is that it’s been migrated to Azure. We did consider migrating this to a web app as well. Unfortunately, not all of the project dependencies could be installed via pip, as they haven’t been built for Windows. We started working around this by installing the wheel files (.whl) manually, but some dependencies did not have wheel files available. After some discussion, we decided to stick with the proven deployment model for the project.

By moving the front-end portion from a user-managed virtual machine to Web Apps, we were able to eliminate Node, Gulp, and other plug-ins/modules used to serve the site. And because the core Angular application itself did not require node, we were able to completely remove the Node server and several thousand files in Node module dependencies!

Another benefit of Web Apps is the continuous integration feature that watches and automatically sets up and deploys code from repositories such as GitHub and local Git repositories. Rex uses private GitHub repositories for source control and collaboration, so it was easy to connect the web application code to Azure. This article describes how to create a GitHub-connected web app through the Azure CLI. However, we set up the integration through the Azure portal by choosing the web app from the dashboard, selecting “Deployment options” from the menu, and following the prompts. (Hint: You can also monitor repository sync history and roll back to previous deployments from this “Deployment options” menu after initial setup.)

While Web Apps does some basic legwork to get web apps up and running, it’s also possible to create deployment scripts for special tasks. The front-end application we migrated uses bower to install web dependencies such as JQuery, so we needed to modify the standard Azure deployment script to run a bower install command. In order to do this, we took the following steps.

  1. We confirmed that the web application included a bower.json file and, if necessary, a .bowerrc file to specify the dependency installation path.

  2. We connected the web app to the GitHub repository by visiting the Azure portal’s Deployment options and following the given prompts.

  3. After the site successfully deployed, we went to the site’s Kudu console by visiting [our-web-app-name].scm.azurewebsites.net. This console gives developers access to more setup and debugging features.

  4. We selected Tools > Download deployment script to download the Azure deployment script files for our site.

  5. We modified deploy.cmd by adding the following code after the KuduSync code in the section labeled “Deployment.” These lines run bower install if a bower.json file is found in the repository.

     :: 2. Bower install
    	
     IF EXIST "%DEPLOYMENT_TARGET%\bower.json" (
       pushd "%DEPLOYMENT_TARGET%"
       call :ExecuteCmd bower install
       IF !ERRORLEVEL! NEQ 0 goto error
       popd
     )
    
  6. We added .deployment and deploy.cmd to the GitHub repository. A few moments later, Azure began building and redeploying the site with the new deployment script.

The first time we pushed these scripts, we saw in the Azure portal that the build failed because of version conflicts in the bower.json file. In order to help Azure resolve these conflicts for us, we added a resolutions object to the bower.json file. For example, we wanted Angular to resolve to version 1.4.9, so we added the following after the dependencies list in bower.json:

"resolutions": {
  "angular": "1.4.9"
  }


Once the repository was updated, the bower install and site deployment succeeded.

Setting up a Linux virtual machine and SSH keys

After completing the web app migration and confirming that it could connect to the AWS virtual machine containing the Python back-end code, we moved on to replicate that virtual machine in Azure through the Azure portal.

First, we created an Ubuntu Server 14.04 LTS Linux virtual machine. Our next step was to generate SSH keys with ssh-keygen and implement the keys in Azure.

To generate and display the contents of an SSH key for user Ubuntu on a virtual machine named azure-server, we ran the following command from bash:

$ ssh-keygen -t rsa -b 2048 -C "Ubuntu@azure-server"

We chose a key name and passphrase as prompted, and private and public keys were generated. We then stored the public key, contained in the .pub file created previously, in the Azure portal.

Setting up a VM on Azure


Tim very kindly authored a blog post describing the entire process of setting up the virtual machine and SSH keys.

Key learnings and conclusions

In our few fast and furious days of hacking on Rex’s web application, Amado shared some positive reflections on Azure. While he admitted that Azure seemed intimidating at first, once he dove in and identified relevant resources, he found the Azure portal easy to navigate and understand.

“Azure is intuitive. Using other services like AWS was way too complicated. That was my main takeaway. I’ve never been as comfortable with AWS as I am with Azure.”

Amado also valued the convenience of a continuous deployment solution that worked with Rex’s existing private repositories. This positive experience with Azure has led Amado to begin experimenting with Azure Machine Learning to model and predict animal health outcomes based on the existed data aggregated and analyzed by Rex.

“You guys need to push Azure to startups more. And Azure Machine Learning is awesome!”

Tim and I came away from the hackfest with our own learnings from a Microsoft perspective. I experienced first-hand some of the challenges faced by small development teams taking on ambitious web application development as Rex has. None of the Rex front-end developers were present during the hackfest, so I relied on Amado’s high-level view, information in readme files, code comments, and GitHub commit history to help answer questions about historical design choices or which repository branches were relevant or abandoned. This experience underscored the importance of developer documentation as well as another benefit of the PaaS approach that I hadn’t considered before. PaaS allows less opportunity for application code to mix with middleware and deployment code that isn’t part of the end product. When we developers can rely on Azure to manage tasks outside of the web application itself, our resulting code will be easier to read and understand. That’s good for us and for the developers that may work alongside or after us.

We had a great time coding alongside Amado and look forward to seeing what Rex does next!

Additional resources