Part 1: Hello, Linux
With all the excitement around Docker in Azure (and Windows Server 10!), I decided it was time to find out what all the fuss was about. My earliest forays were attempted using Vagrant on Windows, which creates Linux VMs using VirtualBox, but that was pretty painful. Every time I killed a VM, it would have to re-download or re-build all the Docker images. Also, running VMs on my Dell XPS13 Ultrabook was not the best performance experience ever.
So I bit the bullet and set up a Linux partition on my laptop. (ElementaryOS, if you're interested, and I like it a lot. Get the Freya beta release.) Which meant all of a sudden I was out of my Visual Studio comfort zone and up to my eyebrows in command lines,
apt-get, Mono, OmniSharp, yo and other such exciting things.
Getting ASP.NET 5 up and running in this environment was not entirely straightforward, so in this post I'm going to try to retrace my steps and share what I had to do.
For the best experience, you want the latest Mono. ElementaryOS Freya is
based on Ubuntu 14.04, which means you can add the Mono Project's package server to your
apt sources and just install using
apt-get. There's a step-by-step guide on the Mono website, but here are those steps for lazy people:
sudo apt-key adv --keyserver keyserver.ubuntu.com \ --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF echo "deb http://download.mono-project.com/repo/debian wheezy main" | \ sudo tee /etc/apt/sources.list.d/mono-xamarin.list sudo apt-get update sudo apt-get install mono-complete
If you're not familiar with Linux shells, the
\ characters there are line continuations.
You used to have to import some certificates after doing this install, but the docs say you don't have to since 3.12. Just in case, that command was:
mozroots --import --sync
You can now write C# code, compile it with
mcs and run it with
mono, plus a bunch more besides. But that's not the point of this exercise...
Installing ASP.NET 5
I've found that a lot of things on Linux can be installed by
curling a shell script from somewhere and piping it to
sh, so it's nice to see that ASP.NET is playing nicely:
curl -sSL https://raw.githubusercontent.com/aspnet/Home/master/kvminstall.sh \ | sh && source ~/.kre/kvm/kvm.sh
That installs everything. After that's finished, run
kvm upgrade to install the latest K Runtime; then run
kvm list and you should see:
Active Version Runtime Location Alias ------ ------- ------- -------- ----- * 1.0.0-beta2 Mono ~/.kre/packages default
Which means you're all set.
Go on, write an MVC application.
This, of course, is not that simple. Even in this brave new world, an ASP.NET MVC application is a complicated thing, with a
project.json and a
Startup.cs and, of course, all the
Views folders. The stuff that Visual Studio used to do for you when you went
FILE > New Project.
It's called "scaffolding", and fortunately, there are command-line-friendly ways to do this sort of thing too. The one a lot of people are using these days is called
yo, which is short for Yeoman (obviously it isn't, but whatever). It's a Node.js package, which means you install it using npm, except this is a new Linux install, which means you don't actually have Node installed. Shocking, I know. Python out-of-the-box, yes; Node, no.
Right, let's install Node, then:
curl -sL https://deb.nodesource.com/setup | sudo bash - sudo apt-get install nodejs
We're nearly there, but the version of
npm that comes with the Node install is ancient (1.4-ish), and
yo wants an up-to-date one (>2.1). This stymied me for a few minutes, but it's actually easy to update
sudo npm update -g npm
Once that's done, you can install
sudo npm install -g yo
Finally, we need to install a generator for
yo. The OmniSharp guys have you covered:
sudo npm install -g generator-aspnet
Aaaaaand... we're done. We can finally create and run an ASP.NET MVC application on Linux.
(SPOILER: THIS IS NOT TRUE. SOMETHING IS GOING TO GO HORRIBLY WRONG. DO NOT WORRY. IT'S ALL PART OF THE INTRICATE STORY I AM WEAVING.)
cd to whichever folder you put your projects under, and run
And you get this:
_-----_ | | .--------------------------. |--(o)--| | Welcome to the | `---------´ | marvellous ASP.NET 5 | ( _´U`_ ) | generator! | /___A___\ '--------------------------' | ~ | __'.___.'__ ´ ` |° ´ Y ` ? What type of application do you want to create? (Use arrow keys) ❯ Console Application Web Application MVC Application Nancy ASP.NET Application Class Library Unit test project
Which is completely brilliant. Use the cursor keys to select MVC Application, then enter a name when it asks for one, and it will generate an empty application for you:
? What type of application do you want to create? MVC Application ? What's the name of your ASP.NET application? Susan info ... Fetching https://github.com/OmniSharp/generator-aspnet/archive/release.tar.gz ... info This might take a few moments ...................... ✔ Done in /home/mark/.cache/yeoman/OmniSharp/generator-aspnet/release create Susan/Controllers/HomeController.cs create Susan/Models/User.cs create Susan/Startup.cs create Susan/Views/Home/Index.cshtml create Susan/Views/Shared/_Layout.cshtml create Susan/project.json create Susan/wwwroot/.gitignore /home/mark/.cache/yeoman Your project is now created, you can use the following commands to get going kpm restore kpm build k run for console projects k kestrel or k webfor web projects
You'll want to
Susan (or whatever you've called your project) before running
kpm restore, but when you do, the K package manager will go off to nuget.org and download all the packages needed to run the application.
Then you can just run
k kestrel and... oh. Crap. That doesn't look good...
System.NullReferenceException: Object reference not set to an instance of an object at Microsoft.AspNet.Server.Kestrel.Networking.Libuv.loop_size () [0x00000] in <filename unknown>:0 at Microsoft.AspNet.Server.Kestrel.Networking.UvLoopHandle.Init (Microsoft.AspNet.Server.Kestrel.Networking.Libuv uv) [0x00000] in <filename unknown>:0 at Microsoft.AspNet.Server.Kestrel.KestrelThread.ThreadStart (System.Object parameter) [0x00000] in <filename unknown>:0
What's gone on there? A quick search revealed an existing GitHub issue with the excellently informative name NullReferenceException when running Kestrel against vNext project on Ubuntu 14.04 LTS, in which it was revealed that the actual problem was that libuv, that stalwart of Nodey event loops, is not installed either. Kestrel is looking for a file on the shared library path called
libuv.so.1 and it can't find it. Honestly, bloody Linux, seems like all you get out of the box is
tar. Oh, and Python.
So how do we install libuv then? That's right, FOSS fans: we build it from source.
apt-get -y install autoconf automake build-essential libtool curl -L http://libuv.org/dist/v1.0.0/libuv-v1.0.0.tar.gz tar xvf libuv-v1.0.0.tar.gz rm libuv-v1.0.0.tar.gz cd libuv-v1.0.0 sh ./autogen.sh ./configure make sudo make install cd .. rm -rf libuv-v1.0.0 sudo ldconfig
That ldconfig line at the end there is important, it updates some kind of thing somewhere that tells Linux what shared libraries it's got and where they are.
And now, after all of that, can you actually run
Yes. Yes, you can. It should just say:
If this were a Node application, you'd stop it by pressing
Ctrl-C, but for some reason that hasn't been working for me. Seems like it's a known issue. I've been working around it by hitting
Ctrl-Z to suspend the process, then
[email protected]:~/asp/Susan$ k kestrel Started
(Here's where I press
+ Stopped k kestrel [email protected]:~/asp/Susan$ ps PID TTY TIME CMD 7428 pts/10 00:00:00 bash 7769 pts/10 00:00:00 k 7773 pts/10 00:00:00 klr 7777 pts/10 00:00:01 mono 7787 pts/10 00:00:00 ps [email protected]:~/asp/Susan$ kill 7777 [email protected]:~/asp/Susan$ fg k kestrel /home/mark/.kre/packages/KRE-Mono.1.0.0-beta2/bin/klr: line 15: 7777 Terminated mono $MONO_OPTIONS "$DIR/klr.mono.managed.dll" "[email protected]" [email protected]:~/asp/Susan$