Echo Linux Commands output using Web API deployed on a Docker VM Container

In this post, I’m going to develop a very simple ASP .NET 5 Web API and deploy that on a Docker container running on Ubuntu server. I’ll implement the HttpGet method for controller that takes the name of the Linux command to be executed. The method will execute the command on host shell using C# and return command output in response to the http request. The purpose is to demonstrate the effective hosting of an ASP .NET Web API on a Linux machine but also highlight the possibilities this unfolds for .Net developers. You can virtually execute any Linux command through an Http call, e.g. installing a third party package, directory listing or checking the total, free and swap memory of your Linux machine. Here's a apt-get call in execution,

Let's Code

Go to File New Project or website

Select Web API from ASP .NET 5 Templates

Delete the ValuesController.cs or edit it to only cater for HttpGet implementation as shown below,

 

  [Route("api/linuxcommand")]
 public class LinuxCommandController : Controller
 {
 // GET api/linuxcommand/du
 [HttpGet("{commandName}")]
 public string Get(string commandName)
 {
 string output = string.Empty;
 
 try
 {
 Process proc = new Process();
 ProcessStartInfo processStartInfo = new ProcessStartInfo(commandName);
 
 processStartInfo.UseShellExecute = false;
 processStartInfo.RedirectStandardOutput = true;
 processStartInfo.RedirectStandardError = true;
 proc.StartInfo = processStartInfo;
 
 proc.Start();
 
 proc.WaitForExit();
 
 if (proc.ExitCode == 0)
 {
 //Success
 output += proc.StandardOutput.ReadToEnd();
 }
 else
 {
 //Failure
 output += proc.StandardError.ReadToEnd();
 }
 }
 catch (Exception ex)
 {
 output = ex.ToString();
 }
 return output;
 }
 }

A bit of explanation. Basically we’re creating a new Process object and passing it the Linux command grabbed as a parameter to the web api call for HttpGet method using ProcessStartInfo. Since we don’t want a separate process yielded and rather rely on Operating System shell (Linux shell in this case), we’re setting UseShellExecute to false.

Additionally we want to read both StandardOuput if the process successfully exited (error code 1) otherwise read StandardError and return that to the Http Get caller.

Also make sure to resolve System.Diagnostics namespace using Quick action,

Also target dnx451 rather than dnxcore50. To do so, go to project.json file and remove the highlighted part of dnxcore50 as System.Diagnostics resolved by Visual Studio will point to dnx451.

Now right click on your project and select publish. In the new dialog box select Docker Containers (the option will only be available to you if you’ve installed Docker Tools for Visual Studio 2015).

Select New

Select the VM of your choice. Since we’re going to deploy our app on a Linux machine, I’ve selected Ubuntu Server. Provide other required parameters and press Ok.

VS will now do the following,

  • Create a VM

  • Manage Resource Group (Creation of Network, Network Interface, etc.)

  • Setup Docker Daemon on the VM

Now once the image is successfully created. Right click on the project again and select publish. You’ll find an option like this,

Go ahead and publish. Now using the Docker file, VS will fetch the asp.net implemtnation from docker hub and build the actual container and deploy that on host VM. Once the process finishes, go to the browser window (or use fiddle if you must) and try to execute a command on Linux VM by hitting the HttpGet method of the web API. Here’s how the output looks like in my case,

Du (Disk Usage)

Reports the sizes of directory inclusive of all of contents and the sizes of individual files.

Vmstat

Reports information about processes, memory, paging, block IO, traps, and cpu activity.

Try commands like ls -al, date or play with chmod on your own :)