Running and debugging CoreCLR ASP.NET web applications on Triton

January 15, 2016 - by Richard Kiene, Joyent Engineer

No need to do a double take, you read that correctly, we’re going to talk about running (and perhaps more importantly, debugging) Microsoft’s newly open sourced CoreCLR and ASP.NET, in Triton secure Linux containers. This previously unlikely pairing brings container-native infrastructure, security, and bare metal performance to a whole new cloud demographic.

Why?

SmartOS aficionados, long time Joyent customers, and people who have never left the Bay Area may be thinking "ASP.NET? Who cares?" Depending on where you look, however, ASP.NET is the second most used server-side language in the world and C# is a top five language when considering web, mobile, and enterprise applications. Suffice it to say, the ability to run C# and ASP.NET on Linux in Triton containers opens a pretty large door.

Getting started

If you don’t already have a Triton account, follow these 3 easy steps to get setup, then setup your Triton Docker endpoint.

Launching your first CoreCLR app on Triton

What we're going to do is run a very basic ASP.NET MVC application that extracts a route value from an HTTP GET request and delivers it back in an HTTP response. If you're curious about the code itself you can check it out here. All of this is prepackaged for you in a Triton Docker container, similar to the following docker file. All that is necessary to get started is running the following command from your workstation:

# Run your container in detached mode with the necessary ports forwarded (8080 in our case).
# Save the instance_id returned from the run command for later use.
$ instance_id=$(docker run -d -P shmeeny/coreclrwebapisample)

Test it out:

# Use the inspect command to extract the IP address property of the running container
# Issue an HTTP GET request to the container using the /values/63 route
$ curl http://$(docker inspect -f {{.NetworkSettings.IPAddress}} $instance_id):8080/values/63
> 63

Starting from scratch

Now that you’ve seen how easy it is to deploy a new CoreCLR application on Triton using a Docker container, let’s remove the Docker layer, and run the application in an infrastructure container. This means you'll need to bootstrap the application and access the container via SSH.

It’s worth noting that Microsoft has some great documentation for getting started with every supported environment, but here we’ll work through just the happy path for creating an Ubuntu 14.04 Triton Linux container, and building a CoreCLR ASP.NET application.

Start by spinning up a new Linux container from the web portal. You’ll want to choose an Ubuntu 14.04 container-native image, and if you’re going to use it much at all, I’d suggest the Triton Standard 0.5 package, but you might get away with less.

Log into your Linux container, install CoreCLR and its dependencies, and add an aspnet user:

$ curl https://gist.githubusercontent.com/richardkiene/c4d0517a68cda66bad65/raw/11d82ace2ca8c2f2cda13838263447e761e06055/install_coreclr.sh -o install_coreclr.sh && chmod +x install_coreclr.sh
$ #I recommend inspecting install_coreclr.sh, but you don’t have to.
$ . ./install_coreclr.sh
$ cd /usr/local/ && mkdir sites && chown aspnet sites

Create a basic Web API Application:

$ su - aspnet # yeoman requires a non-privileged user to create the project
$ cd /usr/local/sites
$ yo aspnet
> Choose Web API Application
> Press return to keep the default name "WebAPIApplication"
$ exit
$ cd /usr/local/sites/WebAPIApplication
$ dnu restore # pulls down app dependencies (like npm install if you’re familiar with npm)
$ dnx web #builds and launches your application

Open another SSH session and run:

$ curl http://localhost:5000/api/values/5

You should see value returned. Additionally, in your other shell session, you’ll see info logging for that request. Congratulations, you’ve just created your first CoreCLR ASP.NET application on Triton!

Deploying from a laptop or workstation

If you’d rather create your application on OS X or Windows, that’s fine too. Microsoft has some handy guides to get you started using OS X and Windows. Once you build your app, you have a couple options for deploying to Triton from OS X and Windows.

Option 1: Clone a your project from a github.com repository into your Triton infrastructure container

$ git clone <your repository>
$ dnu restore
$ dnx <command>

Option 2: Build and deploy with Docker

Yeoman will automatically create a Dockerfile for your project. You can use that to build an image of your project, then push it to a Docker repository like Docker Hub so that you can run it anywhere. That's how I built the Docker image from the example at the top of this post.

Debugging

The great thing about container-native Linux on Triton is that it comes with DTrace, MDB, gcore, and many other fantastic tools which aren’t available on vanilla Linux. So yes, this means you can debug your Microsoft ASP.NET applications with DTrace. Shocked? You’re not alone:

Dtrace meets CoreCLR

We used DTrace and mdb to track down some unnecessarily internationalized string comparisons in the heart of the ASP.NET framework, and Microsoft displayed some great open-source collaboration and worked with us to fix it. Coincidentally, this isn't the first time Joyent has used DTrace and mdb to debug a locale based performance issue.

In a simple benchmark application we put together, we were able to go from ~30ms average response time and ~1105 requests per second, to ~3.35ms average response time and ~14625 requests per second, thanks to DTrace and collaboration with Microsoft. So yeah, that’s a ~10x improvement across the board, yay DTrace!

You can checkout the CoreCLRWebAPISample repository if you're interested in the gory details. Additionally, Microsoft has their own benchmark repository that you can run as well. We found that container-native Linux was on-par with their stated Linux results.

Where do we go from here?

I think it’s safe to say that CoreCLR and ASP.NET on Triton is production ready and on par with most Linux runtime languages. That said, CoreCLR on Triton could be a home run if it had full parity with Node.js, with regard to live and post mortem debugging. Currently, getting symbol information for managed C# function calls is a bit dicey. Your options are attaching with LLDB or doing some very tricky and manual stack unwinding using gcore and mdb. Something akin to Joyent’s mdb_v8 plugin and Node ustack helper for CoreCLR would be a world-class addition to any ASP.NET developer’s toolbox.

I would be remiss if I didn’t call out the outstanding open source collaboration of the Microsoft CoreCLR team. Within minutes of tweeting about working on CoreCLR performance on Triton, they reached out, and within days they were collaborating with us to make huge performance gains. That demonstration of care, passion, and confidence affirms my belief that CoreCLR can and will be a strong option for anyone looking to run their applications on secure, bare metal, containers (i.e. Triton).