Tuesday, November 8, 2022

Azure CI CD Pipeline with Docker in Web API

 Description

               In our prior blogs I have written about how to do CI CD for a web Razor Application for reference click here, Now we are going see how to do the CI CD of a Web API with Docker Containerization in Azure Devops

Prerequisite

ü  Azure Sql Database (I have written blog here about how to create Azure Sql Db)

ü  Little knowledge of Docker

ü  Little knowledge of Web API

ü  C#

ü  Azure Subscription

ü  VS 2022

Our Target

             Now, our target is we are going to create a Web API using .Net 6.0 with Entity Framework; then make the project into containerization then make CI CD and deploy into Azure Container Registry (ACR) Linux system

 

Basics of Docker

Docker is a tool designed to make it easier for developers to develop, ship, and run applications by using containers. Containers allow devs to package an application with all of its requirements and configurations, such as libraries and other dependencies and deploy it as a single package. By doing so, developers can rest easy knowing that the software will work properly on other systems besides the one they used for writing the code.    

First install Docker on our local dev machine, use link to download and install

After installed docker, make the Linux containers on our Docker using the steps

 

Step 1 Create Web API project and move into Azure Artifact

1.  From start menu, open visual studio then click New Project 




2.  Then type Blank solution on the search bar then scroll down little bit select Blank Solution and click Next


3.  The solution name I did mark it as DemoDockerWebAPI and mention the project path and click Create


4.  Next, we are going to add Web Api project to our solution by Right click on the Solution file from Solution Explorer then type Restful api  then from the result select ASP.NET Core Web API Click Next Mention the project name as ApiDemo then mention project location to the same solution folder and click Next


5.  Choose the framework as .NET 6.0 Uncheck HTTPS also at this moment Im not going to include docker so, just leave it as Uncheck and click Create


6.  Now, the solution file is created, Rest API project is also created, Next we are going to create the project in Azure Devops, this I have written here so, please refer it to create new project and move the current project to Azure Devops repository

7.  Now, our project is looks like below structure


8.  Right click on ApiDemo and click Manage Nuget Packages from the Nuget pack window click on Browse then on the search bar type EntityFrameworkCore and press enter, form the result Install below packages with latest versions

a.   Microsoft.EntityFrameworkCore.Design

b.   Microsoft.EntityFrameworkCore.SqlServer

c.   Microsoft.EntityFrameworkCore.Tools

Next we are going to design a table in azure sql database, for info refer my another blog from that Sql DB, created new table called Invoice below is the table structure

 

CREATE TABLE [dbo].[Invoice](

          [invoiceId] [int] IDENTITY(1,1) NOT NULL,

          [entityName] [varchar](100) NOT NULL,

          [invoiceDate] [datetime] NOT NULL,

          [dueAmount] [money] NOT NULL,

          [addDate] [datetime] NOT NULL,

 CONSTRAINT [PK_Invoice] PRIMARY KEY CLUSTERED

(

          [invoiceId] ASC

)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]

) ON [PRIMARY]

GO

 

ALTER TABLE [dbo].[Invoice] ADD  CONSTRAINT [DF_Invoice_addDate]  DEFAULT (getdate()) FOR [addDate]

GO

9.  Next, on VS 2022, open appsettings.json file to configure the connection string of our Azure Sql Dbase


10.              Next, we are going to create Models using scaffold method so, below is the command

a.  Scaffold-DbContext "Data Source={YOUR SERVER NAME OR IP };Initial Catalog={YOUR AZURE SQL DB}; Persist Security Info=False;User ID={YOUR DB USER ID};Password={YOUR DB PASSWORD} ;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=True;Connection Timeout=30;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models

b.  After filled up your db details, execute this command in Package Manager Explorer


c.   After execution, we could see the Models  folder in Solution explorer

11.              Next, Right click on Controllers folder from solution explorer window and click New Controller, from the scaffold window click API then click  API Controller with actions , using Entity Framework and click Add button then select Model calss as Invoice, select the our DataContext file which is under Models folder then make the controller name as InvoicesController then click Add button, it would take some time to create the controller so, wait for some seconds.



12.               Now, the controller has been created, next we are going to run this application and see the result of our end points , when I try to run the POST operation with below data


 but, we are receiving error as “System.InvalidOperationException: Unable to resolve service for type 'ApiDemo.Models.TrainDriverContext' while attempting to activate 'ApiDemo.Controllers.InvoicesController'.” so, strange, why and how this error happens,

a.   The error is from DataContext .cs file, I have commented the OnConfiguring method then

b.   Did move the connection into Program.cs file like below


13.              Then run the application, now Im able to process my data using POST verbose using below json data

 

{

 "invoiceId": 0,

  "entityName": "Kings International Plywood",

  "invoiceDate": "2022-11-08",

  "dueAmount": 15000,

  "addDate": "2022-11-08T11:09:53.909Z"

}


 and click on Execute button and result is 200 SUCCESS

 

So, from the step1 we, knew how to create Web API using Entity Framework and access them

 

Step 2 Create Dockerfile and Docker Compose

 

Next, we are going to implement docker related changes.

 

Usually we do run our project with IIS express from Dev Laptop’s right so, here after we are going to use Docker, the reason why Docker is because, its very helpful for packing and deploying our software’s to avoid manual mistakes.

 

Lets think practically, we have to publish our API in IIS then we will move the Dependency files first then config files then DLL then Batch files right, so, in this order if we missed one config file then what will happen, the entire project will not work and we have to find what cause this error and move that config alone to arreset the error, correct!!

 

When we use Docker, it make our project(s) into a image(IO) format with all dependencies, DLL, Views, configs then this image is going to publish in server so, we avoided manual work and not missing any single file.

 

Hope this explanation is enough, for more informations, we could refer here

 

1.  Right click on APIDemo from solution explorer click Add then click Docker Support


2.  From the Docker File options choose Linux since, we are going use launch our api in Linux environment


3.  Once, this step is completed then immediately VS is start preparing the images on our local Docker, now, open our Docker in laptop we could see the Container with our project name


4.  The dockerfile has lot of commands, we will step through little later, now we are going to add Container Orchestrator so, right click on API Demo cick New then click Container Orchestrator Support


 
from the popup window select Docker Compose and click Ok

then from the OS selection choose Linux and click Ok


5.  Now, we do have new project in Solution explorer called Docker-Compose like below, which means here after we are not going to run our application via IIS Express rather its Docker                       


6.  So, the docker file commands are going use the related packages from mcr.microsoft.com/dotnet/aspnet:6.0

a.   Next move it into app folder

b.   Then it find the csproj file from original location to build location

c.   Then it start build the project from the new location(not the actual source)

d.   When its build then start make publish the files into /app/publish location

7.  Lets run the project now, and make sure are we able to get data from Invoice controller, well its working for us 


 

 

 

Step 3 how to create Azure Container Registry

1.  Open portal.azure.com from your web browser and login with your credentials, then after from the home page search bar type Container registries then at the bottom select the service called Container registries then click + Create

a.   Type Registry name as DockerCICDDemo

b.   Location West Europe

c.   Resource group as RG-Docker

d.   Sku as Basic

e.   Click Review + Create at the end of the tabs click Create button


f.    This will take some time, once its completed then click on Go to resource

g.   Then Access Key from the left pane there click Admin User Enabled  since, this is the keys which is going to access in ACR from next step


Step 4 How to create Build CI from Azure Devops for Container

1.  Before this step, Push all the docker, controller, models from git to Azure Repository

2.  Then after visit dev.azure.com, within the organization choose the project then click Pipelines and click Create pipeline


3.  From the next menu click Classic Editor


4.  Choose source as Azure Repos Git then automatically the project, Repository, Branch are selected then click Continue


5.  From the template window choose Docker Container and click Apply


6.  Next window is like below, here we are going to setup which to build as image and where from the repo take, from below steps


a.   Change the name of pipeline into DockerDemoCI from DockerCICDDemo-Docker Contain…

b.   Agent Pool as Azure Pipelines

c.   Agent Specification as ubuntu-20.04


d.   Click Agent Job 1, change the display name as Dev-Agent job 1

e.   Agent pool as Azure Pipelines

f.    Agent Specification as ubuntu-20.04

g.   Click on Build an Image

h.  Container registry type as Azure Container Registry

i.    Authorize subscription with Azure Service Authorization

j.    On the Azure Container Registry section choose our ACR created in above steps as DockerCICDDemo

k.   By Default the docker file section is wrong so, we have to choose the exact location of docker file by clicking the browse button


l.    Click Push an image , keep Container Registry Type as Azure Container Registry

m. Azure Subscription  by Service subscription

n.  Choose Azure Container Registry as DockerCICDDemo

o.  Go to Triggers tab and tick Enable Continuous integration then click Save & Queue

p.   To all other places Keep it by default, then click Save & Queue which will start build our project.


7.  From the upcoming page click Dev-Agent job1, will show the logs


8.  Unfortunately we received an error at step 6/20 as COPY failed: file not found in build context or excluded by .dockerignore: stat ApiDemo/ApiDemo.csproj: file does not exist 

9.  It says that the Container is not able to find our CSPROJ file, which is the core file has all references of our project so, go back to our VS2022 project and open Dockerfile
a.   Made a change into COPY ["ApiDemo.csproj", "ApiDemo/"] from COPY ["ApiDemo/ApiDemo.csproj", "ApiDemo/"]
10. Then after PUSHED the code change and CI is automatically taken to build since, we activated it in Trigger section but, again we received error at step 10 so, we proud that moved 4 steps ahead . Complete error message is “CSC : error CS5001: Program does not contain a static 'Main' method suitable for an entry point [/src/ApiDemo/ApiDemo.csproj]”

a.   To resolve this error, again we have to add new change in Docker file like below , the change I made is added another COPY . .(highlighted in yellow) after this change push it then this time the BUILD is success and all are fine

#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

 

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base

WORKDIR /app

EXPOSE 80

 

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build

WORKDIR /src

COPY ["ApiDemo.csproj", "ApiDemo/"]

RUN dotnet restore "ApiDemo/ApiDemo.csproj"

COPY . .

WORKDIR "/src/ApiDemo"

COPY . .

RUN dotnet build "ApiDemo.csproj" -c Release -o /app/build

 

FROM build AS publish

RUN dotnet publish "ApiDemo.csproj" -c Release -o /app/publish /p:UseAppHost=false

 

FROM base AS final

WORKDIR /app

COPY --from=publish /app/publish .

ENTRYPOINT ["dotnet", "ApiDemo.dll"]


 

Step 5 Create Azure App Service with Docker Container

Here we are going to create the App Service to launch our API with Docker Container

 

1.  Go to portal.azure.com and login

2.  From Home page, Click App Services then click + Create

a.   From the configuration tabs Resource group as RG-Docker

b.   App name as DockerCiCdDemoApp

c.   Publish Docker Container

d.   Operating System Linux

e.   Region West Europe

f.    Customized App Service Plan as AppServicePlan-Linux(f1)

g.   Pricing plan Click Change Size from the popup select Dev/Test and select F1  for free of cost then click Apply


h.  Click Next: Docker

i.    On Docker tab Options as Single Container

j.    Image Source as Azure Container Registry

k.   Registry as DockerCICDDemo

l.    Then Image is automatically comes front since, this is the only image available under the registry DockerCICDDemo

m. Click Next and click Yes in Application Insights under Monitoring

                                      i.    Create new Application insight as AppInsightsDockerDemo

                                    ii.    Region as West Europe

n.  Click Review + Create then click Create


3.  Now, we have Azure Devops CI, ACR(Azure Container Registry), App Service for our API are ready. Next we are going to create Release CD pipeline

 

Step 6 How to create Azure Release Pipeline CD

 

With this release Pipeline we are going to make the successfully build projects to move into server to publish.

1.  Go back to azure devops, Click Releases under Pipelines then click New Pipleline 


2.  From the next window choose Azure App Service deployment  and click Apply


3.  Rename Stage 1 into Dev

4.  Click Add an artifact, from the popup project is by default got select then choose the build name DockDemoCI  and click Add


5.  Click on Flash symbol like below screenshot, there Enable Continuous deployment trigger this will make the deployment happens when the build CI is succeeded .


6.  Click 1 job 1 task from Dev it


7.  On the Dev Azure Subscription as Service Subscription

a.   App type as Web App for containers(Linux)

b.   App service name as DockerCiCdDemoApp

c.   Repository as dockercicddemo, this we can copy, paste from Azure portal under Azure Contrainer Services under Repositories (these we have created in earlier steps, FYR)


d.   Registry or namespace as dockercicddemo.azurecr.io this is also we have created earlier, please refer below screenshot

 


e.   Change New release pipeline into CD DockerCD-Demo

f.    Click Run on agent

g.   Agent pool as Azure Pipelines

h.  Agent specification ubuntu-20.04

i.    All others are by default

8.  Click on Deploy azure app service

a.   Connection type as Azure Resource Manager

b.   All others are ok just keep as it is, click Save

9.  For the first time we do manual start the service since, now we didn’t made any new code change and push into devops so, CI wont run automatically because of this CD wont start automatically so, we are going to manually make it start Create release button from the top


10.              From the next screen Dev Pipeline flash and click Create button then a small div opens and says that Release 1 has been created , click on that, on the next screen Mouse hover on Dev, Click on Deploy


11.              Wanna see the logs then click the logs button it shows logs like below


 at the end it shows Succeeded message

 

Step 7 How to call the API

1.  Go back to azure portal , open Azure App Services and click copy the URL


2.  So https://xxxxx.azurewebsites.net/api/Invoices is the payload when we run it in browser then we could see the output in json format like below

 


Conclusion:

             Now, we know how to deploy the Docker-based Web API project into Azure using the Containerization CI CD pipeline.

Azure CI CD Pipeline with Docker in Web API

  Description                In our prior blogs I have written about how to do CI CD for a web Razor Application for reference click here ...