Build And Deploy Your First .NET Core Web App As Docker Container Using Microsoft Azure - Part One

In this article, you will learn how to build and deploy your first .net core web app as docker container using Microsoft Azure.

Do you often ask yourself: I have built an ASP .Net Core Web Application, now what? How do I take it to the next level using tools and platforms like GitHub, Docker, CI/CD and Microsoft Azure with my application?
 
If the answer is "yes,"  you are at the right place!
 

Introduction 

 
This article is the first in the series where we are going to build a simple ASP .Net Core web application, containerize it with Docker and run it on local host. And we will push everything to GitHub for later use.
 
In later posts, we will setup Microsoft Azure DevOps Build pipeline to automate the process of building and pushing the Docker image to Docker Hub. Next, we will use Azure DevOps Release pipeline to deploy our application on Azure Web App Service as a container.
 
So, stay with me --  there is a lot to cover. Let's get started!

Setup a GitHub Repository

 
The first step is to setup a repository on GitHub where you are going to put all your code. This is required, because at a later stage you will setup Azure to trigger a build and release, each time you do a push to your repository.

So login to your GitHub account and create a repository.

Once you have created a repository, it's time to get it to your local system and start hacking. But before you do that, please make sure that you have Git installed on your system, if not head on to Git download page and set it up. It's easy!

Now, on GitHub, select the repository you have just created. To the right you should see "Clone or download" button, click on it and you have the URL to clone your repository.

Build And Deploy Your First .NET Core Web App As Docker Container Using Microsoft Azure
 
Open up a terminal or powershell session, navigate to the directory where you want to clone the repository and execute the command:
  1. $ git clone <repository-clone-url>  
With that set, we are ready to start developing our application.
 

Create an ASP .Net Core Web Application

 
In order to create the application you must install .Net Core (version >= 2.0). Go to .Net Core download page and install the SDK compatible with the underlying system.

Now, if you are on Windows open Visual Studio and create a new ASP .Net Core Web Application Project.

Build And Deploy Your First .NET Core Web App As Docker Container Using Microsoft Azure
 
New ASP .Net Core Web Application ProjectOn the next page, select the Web Application (Model-View-Controller) template and ensure that "Configure for HTTPS" is unchecked. Just keep it simple. Click OK.

If you are on Linux or Mac OS, open a terminal and navigate to the clone directory. You can create a .Net Core MVC Web App using the following command:

  1. $ dotnet new mvc --name <your-project-name>  

Once done, you can now use your favorite editor to make required changes.

For further learning or solving an issue, I would highly recommend you checkout my YouTube video playlist about Getting started with .Net Core on Linux or Mac OS.

At this point, I leave it to you, my dear reader, to come up with an idea of your simple application and bring it to life. Or you can follow along as I make the changes to my application.

I am building a simple blog that displays a list of latest articles. Please feel free to clone my GitHub repository to get the latest of source code and all the resources used. 

Adding Articles Link to Navigation Bar

An ASP .Net Core web application comes with a neat predefined template. To update the navigation bar, open Views/Shared/_Layout.cshtml. Under body>nav section add a link for Articles:

  1. ...  
  2. <nav class="navbar navbar-inverse navbar-fixed-top">  
  3.     <div class="container">  
  4.         <div class="navbar-header">  
  5.             <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">  
  6.                 <span class="sr-only">Toggle navigation</span>  
  7.                 <span class="icon-bar"></span>  
  8.                 <span class="icon-bar"></span>  
  9.                 <span class="icon-bar"></span>  
  10.             </button>  
  11.             <a asp-area="" asp-controller="Home" asp-action="Index" class="navbar-brand">Docker WebApp</a>  
  12.         </div>  
  13.         <div class="navbar-collapse collapse">  
  14.             <ul class="nav navbar-nav">  
  15.                 <li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>  
  16.                 <li><a asp-area="" asp-controller="Home" asp-action="Articles">Articles</a></li>  
  17.             </ul>  
  18.         </div>  
  19.     </div>  
  20. </nav>  
  21. ...   
Now, when we click on the Articles link, an HTTP GET request will be sent Articles action in the Home controller, which is yet to be updated.
 

Adding required models

Under the Models directory, add a .cs file ArticlesViewModel.cs, which will have the required model classes:

  1. using System;  
  2. using System.Collections.Generic;  
  3.   
  4. namespace WebApp.Models  
  5. {  
  6.     public class ArticlesViewModel  
  7.     {  
  8.         public List<Article> Articles { getset; }  
  9.   
  10.         public ArticlesViewModel()  
  11.         {  
  12.             Articles = new List<Article>();  
  13.         }  
  14.     }  
  15.   
  16.     public class Article  
  17.     {  
  18.         public int Id { getset; }  
  19.         public string Title { getset; }  
  20.         public string Author { getset; }  
  21.         public DateTime PublishedOn { getset; }  
  22.         public string Content { getset; }  
  23.     }  
  24. }  
Next, let's add some static data to our blog using the ArticleRepository.cs:
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using WebApp.Models;  
  5.   
  6. namespace WebApp  
  7. {  
  8.     public class ArticleRepository  
  9.     {  
  10.         private List<Article> articles = new List<Article>  
  11.         {  
  12.             new Article  
  13.             {  
  14.                 Id = 1,  
  15.                 Title = "What is Lorem Ipsum?",  
  16.                 Author= "Gaurav Gahlot",  
  17.                 PublishedOn = new DateTime(2019, 01, 20),  
  18.                 Content = "Lorem Ipsum is simply dummy text of the printing and typesetting industry."  
  19.             },  
  20.         }  
  21.   
  22.         public List<Article> GetLatest()  
  23.         {  
  24.             return articles;  
  25.         }          
  26.     }  
  27. }  

Updating the Home Controller

The Home controller needs to have an action that can handle the requests coming for a list of the latest articles. Here is the new controller with Articles action for GET requests:

  1. using Microsoft.AspNetCore.Mvc;  
  2. using System.Collections.Generic;  
  3. using System.Net.Http;  
  4. using WebApp.Models;  
  5.   
  6. namespace WebApp.Controllers  
  7. {  
  8.     public class HomeController : Controller  
  9.     {  
  10.         public IActionResult Index()  
  11.         {  
  12.             return View();  
  13.         }  
  14.   
  15.         public IActionResult Articles()  
  16.         {  
  17.             var model = new ArticlesViewModel();  
  18.             model.Articles = new ArticleRepository().GetLatest();  
  19.   
  20.             return View(model);  
  21.         }  
  22.     }  
  23. }  
The last thing we need to do is to add a View that will render our data. So, add an Articles View under Views/Home/ with the following code to render the latest articles,
  1. @{  
  2.     ViewData["Title"] = "Articles";  
  3. }  
  4. <div id="myCarousel" class="carousel slide" data-ride="carousel" data-interval="6000">  
  5.     <div class="carousel-inner" role="listbox">  
  6.         <div class="item active">  
  7.             <img src="~/images/docker.png" alt="Docker" class="img-responsive" />  
  8.             <div class="carousel-caption" role="option">  
  9.                 <p style="font-size:xx-large; color:darkslategrey">  
  10.                     If you see me swim, your application is up and running in Docker.  
  11.                 </p>  
  12.             </div>  
  13.         </div>  
  14.     </div>  
  15. </div>  

Push your code to GitHub

Once you are done making the code changes, it's time to push your code on GitHub. Open a terminal and navigate to the project directory.

You can check the status of your local repository using the command,
  1. $ git status  

You should see all the files and directories being added or update. Now, to stage all the changes in your repository run the command,

  1. $ git add .  

Let's commit the changes with a short meaningful message,

  1. $ git commit -m "your-commit-message"  

Finally push all the committed changes to remote branch on GitHub,

  1. $ git push origin  

Note
It is not a good practice to commit all the changes at the end. In fact, you should frequently commit all the changes that can be grouped logically.

At this point, I am assuming that your application is working well and you are ready containerize your application with Docker. 

Dockerfile

According to Docker documentation,

A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image. Docker can build images automatically by reading the instructions from a Dockerfile.

Here is the Dockerfile for my application,

  1. # STAGE01 - Build application and its dependencies  
  2. FROM microsoft/dotnet:2.1-sdk AS build-env  
  3. WORKDIR /app  
  4. COPY WebApp/*.csproj ./  
  5. COPY . ./  
  6. RUN dotnet restore   
  7.   
  8. # STAGE02 - Publish the application  
  9. FROM build-env AS publish  
  10. RUN dotnet publish -c Release -o /app  
  11.   
  12. # STAGE03 - Create the final image  
  13. FROM microsoft/dotnet:2.1-aspnetcore-runtime  
  14. WORKDIR /app  
  15. LABEL Author="Gaurav Gahlot"  
  16. LABEL Maintainer="quickdevnotes"  
  17. COPY --from=publish /app .  
  18. ENTRYPOINT ["dotnet""WebApp.dll""--server.urls""http://*:80"]  
Note that I'm using a multi-stage build to ensure that the final image is as small as possible.

At a high level, a multi-stage build is much like what we generally do while building and publishing our projects. Here is a brief breakdown of the stages,

  • STAGE01 - At this stage we restore the packages and dependencies our application requires to build. Notice that the building the project .Net Core SDK, which is our base image.
  • STAGE02 - Once the first stage is successful, we publish our application and store the generated binaries in /app directory.
  • STAGE03 - In this stage we use the .Net Core Runtime as our base layer and copy the binaries from /appdirectory, generated in previous stage.

It's a great feature to minimize the size of your Docker images and you can read more about it from the docs.

Because this Dockerfile is specific to my application, you might have to make some changes for it to work.

Running a Container

It's time to build a Docker image for your application and spin up a container. Open up a terminal and navigate to the directory where the Dockerfile is saved. Now build a Docker image using the command:

  1. $ docker build -t webapp .  

This will build a Docker image and keep it on our local system. To test our image and application we will now run a container using the command:  

  1. $ docker run -d -p 5000:80 --rm --name webapp webapp  
  2. 19c758fdb9bfb608c4b261c9f223d314fce91c6d71d33d972b79860c89dd9f15  

The above command creates a container and prints the container ID as output. You may verify that the container is running using the docker ps command. 

  1. $ docker ps  
  2. CONTAINER ID        IMAGE               PORTS                  NAMES               MOUNTS  
  3. 19c758fdb9bf        webapp              0.0.0.0:5000->80/tcp   webapp  

Now, open a browser and go to the URL http://localhost:5000/.

If everything is working fine, you must see your web application's home page. In my case it looks like this,

Build And Deploy Your First .NET Core Web App As Docker Container Using Microsoft Azure 
Test your application and once you are sure that it's working commit and push the Dockerfile to your GitHub repository.
 

Conclusion

In this we have developed a web application using ASP .Net Core and put it on a GitHub repository. We also tested our application by building a Docker image and running a Docker container out of it.

The next step is to setup a Build pipeline on Microsoft Azure DevOps. This pipeline will connect with our GitHub repository. We will also set the pipeline to trigger a build each time a push is made to a master branch on the repository. The pipeline will create a Docker image and push it to Docker Hub.