Getting Started With Mono on Docker

It’s barely two years since Docker was released and there are now over 13,000 images available to download from the Docker Hub. If you are new to Docker, it’s best described as a way of packaging an application and its dependencies inside a virtual container that can run on any Linux server. This is a lot less demanding than packaging an app in a virtual machine and operating system.
Programming Mono Apps
After Java and C/C++, the next most popular programming language is C#, and it’s part of the .NET world on Windows. Not long after C# was released, the Mono project was launched to develop the equivalent of .NET, but running on Linux and Mac. Despite initial suspicion that it was a way for Microsoft to attack Linux through patents, it has grown and now underpins the cross-platform mobile development system Xamarin.
There are some key differences between .NET and Mono, for example WinForms and WPF are Windows only, but by and large you can take most .NET compiled C# executables, copy them to a Linux system that has Mono installed, and this command:
1 |
Mono AppName.exe |
… will run the App.
The purpose of this post is to provide an example for how to use Docker with the Mono technology.
Why Docker?
Why is Docker so good? Say you want to try something out on Nginx or Centos, or PostgreSQL. Without Docker you could spend hours installing them, configuring, etc. With Docker, you can do it in literally seconds.
Docker is open source and will appear in the next Windows 2016 Server release, but for now its use is limited to Linux and Mac OS X. Using the open source Oracle VirtualBox as I did lets you install Docker, running in a virtual machine inside VirtualBox, on Windows. You could, for example, install a full Linux such as Ubuntu Server into VirtualBox, or use a special helper application called Boot2Docker.
Let’s Dock
If you’re new to Docker, read the user guide. You need to understand running apps, working in containers and daemonizing apps. It’s not terribly difficult; the user guide pages are well written and easy to read.
It gets a little more complicated when creating an app to run in Docker. The app I’ve created is a simple “calculate the first 1,000 primes” in C# using the sieve of Eratosthenes. It outputs all the primes between 2 and 1,000. This compiles and runs on Windows, and will run on any Linux system with Mono installed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
using System; namespace sieve { class Program { const int HiPrime=1000; static readonly bool[] Primes = new bool[HiPrime];//by default they're all false private static void Main(string[] args) { for (var i = 2; i < HiPrime; i++) { Primes[i] = true;//set all potential primes true } for (var j = 2; j < HiPrime; j++) { if (!Primes[j]) continue; for (long p = 2; (p * j) < HiPrime; p++) { Primes[p * j] = false; } } for (var index = 2; index < Primes.Length; index++) { if (Primes[index]) Console.WriteLine(index); } } } } |
We want to run this aplication inside a container. Let’s look at a simpler application — Hello World — first and then return to this.
For the sake of completeness, we’ll run Hello World under Ubuntu 14.04 (Trusty Tahr). If you have installed Docker, you can run the one line Hello World with this command.
1 2 3 |
sudo docker run ubuntu:14.04 /bin/echo 'Hello world' <a href="http://thenewstack.io/wp-content/uploads/2015/05/runningecho.gif"><img class="alignnone size-full wp-image-369892" src="http://thenewstack.io/wp-content/uploads/2015/05/runningecho.gif" alt="Running Hello World in Docker" width="650" height="261" /></a> |
Here, Ubuntu 14.04 is the container. The first time you run this it will download the container and install it, which takes about a minute, or slightly longer for a 68 MB image. Then it runs the command /bin/echo ‘Hello World’ and that just outputs Hello World on the terminal. On second and subsequent runs, it runs immediately.
So to run the sieve app, we need to make sure Mono is installed as we need to both compile sieve and run it. The Docker registry lists a bunch of Mono repositories and the first one seems popular. That first Mono link takes you to this page.
Now to define what happens, we need to create a file, specifically one called Dockerfile.
What is a Dockerfile?
A Dockerfile is a text file that contains all the instructions to fetch and build the software.
The reference pages include a page about Dockerfiles. For the example sieve program, it’s a very short file. Here’s the Dockerfile I cobbled together:
1 2 3 4 |
FROM mono:latest ADD . /home/david/sieve RUN mcs /home/david/sieve/sieve.cs CMD [ "mono", "/home/david/sieve/sieve.exe" ] |
Commands are in uppercase. FROM specifies the Mono image to use. In this case it’s mono:latest. You can specify which version of Mono you wish to use here. ADD copies the files into the specified folder, RUN uses the Mono compiler mcs to compile it and CMD runs the exe with the Mono command.
The first time you run the build, it will fetch anything it doesn’t have locally. This command builds it:
1 2 3 |
sudo docker build -t sieve . <a href="http://thenewstack.io/wp-content/uploads/2015/05/build.gif"><img class="alignnone size-full wp-image-369893" src="http://thenewstack.io/wp-content/uploads/2015/05/build.gif" alt="Docker Build" width="640" height="405" /></a> |
Then this command runs it:
1 2 3 |
sudo docker run sieve <a href="http://thenewstack.io/wp-content/uploads/2015/05/runsieve.gif"><img class="alignnone size-full wp-image-369894" src="http://thenewstack.io/wp-content/uploads/2015/05/runsieve.gif" alt="Running Mono Sieve App on Docker" width="640" height="255" /></a> |
And voila, one Dockerized Mono app with the last of the prime numbers showing. Now there’s a lot more to Docker, for example daemonizing apps is particularly important as that makes web and other servers possible.
Conclusion
Docker is a very convenient and time saving way to try out software on different platforms. It makes it easy to move software from development to production consistently. It allows applications to be put in a container with an operating environment, similar to running on a virtual machine but taking up way less space. Virtual machines each have a copy of the OS and can be many gigabytes in size. With Docker there’s really only one operating system that’s shared.