Michael Friis' Blog

About


Building Heroku buildpack binaries with Docker

This post covers how binaries are created for the Heroku Mono buildpack, in particular the Mono runtime and XSP/fastcgi-mono-server components that are vendored into app slugs. Binaries were previously built using a custom buildpack with the build running in a Heroku dyno. That took a while though and was error-prone and hard to debug, so I have migrated the build scripts to run inside containers set up with Docker. Some advantages of this approach are:

  • It’s fast, builds can run on my powerful laptop
  • It’s easy to get clean Ubuntu Lucid (10.04) image for reproducible clean-slate builds
  • Debugging is easy too, using an interactive Docker session

The two projects used to build Mono and XSP are on GitHub. Building is a two-step process: First, we do a one-time Docker build to create an image with the bare-minimum (eg. curl, gcc, make) required to perform Mono/XSP builds. s3gof3r is also added – it’s used a the end of the second step to upload the finished binaries to S3 where buildpacks can access them.

The finished Docker images have build scripts and can now be used to run builds at will. Since changes are not persisted to the Docker images each new build happens from a clean slate. This greatly improves consistency and reproducibility. The general phases in the second build step are:

  1. Get source code to build
  2. Run configure or autogen.sh
  3. Run make and make install
  4. Package up result and upload to S3

Notice that the build scripts specify the /app filesystem location as the installation location. This is the filesystem location where slugs are mounted in Heroku dynos (you can check yourself by running heroku run pwd). This may or not be a problem for your buildpack, but Mono framework builds are not path-relative, and expect to eventually be run out of where they were configured to be installed. So during the build, we have to use a configure setting consistent with how Heroku runs slugs.

The build scripts are parametrized to take AWS credentials (for the S3 upload) and the version to build. Building Mono 3.2.8 is done like this:

$ docker run -v ${PWD}/cache:/var/cache -e AWS_ACCESS_KEY_ID=key -e AWS_SECRET_ACCESS_KEY=secret -e VERSION=3.2.8 friism/mono-builder

It’s now trivial to quickly create and upload to S3 binaries for all the versions of Mono I want to support. It’s very easy to experiment with different settings and get binaries that are small (so slugs end up being smaller), fast and free of bugs.

There’s one trick in the docker run command: -v ${PWD}/cache:/var/cache. This mounts the cache folder from the current host directory in the container. The build scripts use that location to store and cache the different versions of downloaded source code. With the source code cache, turnaround times when tweaking build settings are even shorter because I don’t have to wait for the source to re-download on each run.

Heroku .NET buildpack now with nginx

Another weekend, and another bunch of updates to the .NET buildpack. Most significantly, ASP.NET apps now run with  fastcgi-mono-server fronted by an nginx instance in each dyno. This replaces the previous setup which used the XSP development web server. Using nginx is supposedly more production ready.

Other changes include setting the LD_LIBRARY_PATH environment variable and priming the Mono certificate store. This will make apps that use RestSharp, or otherwise exposes Mono’s reliance on native zlib, work out of the box. It also makes calling HTTPS web services form Heroku not fail.

These improvements came about because people tested their .NET apps on Heroku. Please do the same so that we can weed out as many bugs as possible. If you want to contribute, feel free to check out the TODO-list in the README on the GitHub.

Heroku .NET buildpack update to Mono 3.2 and more

Hot on the heels of posts on Running .NET on Heroku and Running OWIN/Katana apps on Heroku, I’m happy to announce a couple of updates to the buildpack:

  1. Now uses the newly released Mono 3.2 runtime. I need to figure out some way for users to select what version they want the same way the Python buildpack uses runtime.txt.
  2. Adds symbolic links from NuGet.targets files to nuget.targets files to account for inconsistent casing practices in NuGet.
  3. Fetches Nuget.targets file that is not broken when doing package restore on Linux. I’m still trying to get Microsoft to accept a pull request to NuGet that fixes this.

I’ve also spent some time trying to switch from xsp4 to nginx and fastcgi-mono-server4, but am currently stuck.

Running OWIN/Katana apps on Heroku

This post demonstrates how to get a an OWIN/Katana sample app running on Heroku. It uses the Mono buildpack that I’ve already covered on the blog. As far as I can determine, Heroku is the only public platform where you can conveniently prototype and share OWIN apps running on Katana.

OWIN and Katana

OWIN is the Open Web Interface for .NET, a specification for how apps and frameworks should interact with servers that host them. It’s very much like Ruby Rack, only for .NET. By decoupling apps from web servers, it should become much easier to write portable middleware that can be reused between apps and  frameworks. There’ already a ton of good OWIN stuff on NuGet.

Katana is a set of components (including a web server) built by Microsoft and others that conforms to the OWIN spec. Here’s a great overview write-up about Katana. There are other OWIN compliant servers (like Kayak) and hopefully more will show up.

OWIN and Microsoft adopting OWIN is pretty exciting: It will make writing good .NET web apps easier and it’s going to free .NET web developers from their historical over-reliance on the IIS web server. With IIS out of the picture, hosting apps on Mono and on open platforms like Heroku will be much easier.

Getting started

The sample demoed here is an expanded version K. Scott Allen’s sample. Here’s how to get started:

  1. Open Visual Studio and Create a C# Console Application and enable NuGet package restore. I used Visual Studio 2012 and named the app KatanaTest.
  2. Install OWIN NuGet packages
    install-package Microsoft.Owin.Hosting -IncludePreRelease
    install-package Microsoft.Owin.Host.HttpListener –IncludePreRelease
    install-package Microsoft.Owin.Diagnostics –IncludePreRelease
    install-package Owin.Extensions -IncludePrerelease
  3. Add a class that configures the app to just display the Katana sample page.
  4. Add a Main entry point that listens for HTTP on a port specified as a command line argument and waits for ctrl+c to exit.
  5. Add a Procfile that tells Heroku how to start the app, passing in the $PORT as an argument.
  6. Fix casing bug and restore command to make project build on Heroku (these will hopefully soon be fixed in NuGet). (Fixed in latest buildpack version)
  7. Deploy to Heroku:
        $ heroku create
        $ heroku config:add BUILDPACK_URL=https://github.com/friism/heroku-buildpack-mono/
        $ git push heroku master

Check out the sample running live on Heroku. The sample project is available on GitHub.

Running .NET on Heroku

Since joining Heroku I’ve been wanting to get .NET running on the platform and I’m happy to report that we now have a reasonably workable Mono buildpack. My goal was to be able to take an ASP.NET MVC solution created with Visual Studio on Windows, create a Heroku app, run git push heroku master and have Heroku build, deploy and run the app using Mono and the XSP web server.

The result is based heavily on previous work by my colleague Brandur.

Getting started

To use the .NET buildpack, create an ASP.NET MVC 4 web site and enable NuGet package restore. There are then a few tweaks required to make the solution palatable to Mono and xbuild (striked-out issues have been fixed in buildpack and are not necessary anymore):

Hopefully, we can get these obstacles eliminated through improvements to either Mono, NuGet or the buildpack.

Now, deploy to Heroku:

    $ heroku create
    $ heroku config:add BUILDPACK_URL=https://github.com/friism/heroku-buildpack-mono/
    $ git push heroku master

I’ve created a few samples that are known to work. TestingMono is an extremely simple MVC site with a background worker that logs a message once every second. To run the background worker, add a Procfile that defines the command worker: mono WorkerTest.exe and scale it to 1 with heroku scale worker=1. The other sample is forked from an AppHarbor sample and demonstrates simple use of a Heroku PostgreSQL database. Note that the connectionstring has to be read from the environment, not Web.config as is usual in .NET. You can find the sample running here.

Overview

Here’s what works:

  • Running ASP.NET MVC 4 on top of Mono 3.0.11 and XSP 3.0.11
  • NuGet package restore so you don’t have to include library dependencies in your repo
  • Caching of build output and incremental builds, including caching of already-downloaded NuGet packages
  • Running executables in background worker dynos

Here’s what needs love:

  • Insertion of config into appSettings in Web.config
  • Make more of the default Visual Studio templates work out of the box
  • Look for XSP replacement (likely nginx)

Also see the TODO in the README. Contributions are very welcome. I hope to cover how buildpack dependencies (Mono and XSP in this case) are generated in a future blog post.

And yes, I’m working on getting Visual Basic running.