Create your first (asp.net core 2.0) Service Fabric container application on Windows

So it all started when I wanted to host a very basic asp.net core api app on Azure. i had many options like hosting as app service or hosting inside service fabric or hosting inside service fabric using containers. The third option is something I wanted to explore more as I had almost no knowledge on this topic except what an image & what a container means. So i started reading & reading. Went through a few videos on pluralsight, mainly this one. I was at last able to successfully able to create a docker image on my local and deploy locally (more on that in some other post). So only thing left was to deploy & test the same on Azure. But then I spend hrs. to figure out the process. Though many things are documented in msdn but no where it was end to end. So I thought of writing it down in detail step by step on how to create an image till the point of hosting in Service Fabric as a containerized service. Please bare with me as I paste a few images along with. Code will be available below.

Note: All the steps that are described here are true as per today's releases. If things are updated later I'll try to update this post too :)

Prerequisites

A development computer running:
  • Visual Studio 2017 (mine is v15.5.2)
  • Service Fabric SDK and tools. My current version is SDK: 2.8.232.9494 and Runtime: 6.0.232.9494
  • Docker for Windows. Get Docker CE for Windows (stable). After installing and starting Docker, right-click on the tray icon and select Switch to Windows containers. This is required to run Docker images based on Windows. My current version is v17.12.0-ce-win47 (15139)
  • A basic Windows Service Fabric cluster with one node (for testing purpose only) running on Windows Server 2016 with Containers. Make sure you expose port 8080 for this activity - Details here
  • A registry in Azure Container Registry - Details here

Create a new asp.net core 2.0 api app

Not going into details, you can find many articles to start with asp.net core 2.0. But at the end its a basic api app. below is the solution structure.
Typical asp.net core 2.0 solution structure
Typical asp.net core 2.0 solution structure
The controller has a basic get method to get top n random quotes/lines, nothing special. I copied it from this blog post.

Create a docker image (locally)

Here comes the interesting part when you need to create a docker image (based on windows). So lets first create a docker file inside the solution. Add a new file called DockerFile in the project. And add below lines. Shall explain in details.

# BUILD PHASE
FROM microsoft/aspnetcore-build:2.0.5-2.1.4-nanoserver-sac2016 AS build-env
WORKDIR /app
COPY *.csproj .
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o out

# RUN PHASE
FROM microsoft/aspnetcore:2.0.5-nanoserver-sac2016
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "DockerWebTestApp.dll"]

There are many ways to build an asp.net core api app & build an image, e.g. you can build in your own machine & then containerize it from the published location. Or you can actually build & publish inside a container & then create an image out of it. I'm taking the 2nd route here.

Let's explore whats the 'BUILD PHASE' in the docker file. Let me write the 6 lines under the build phase in plain English.
  1. Get an image named 'microsoft/aspnetcore-build' created by Microsoft from hub.docker.com that has tag as '2.0.5-2.1.4-nanoserver-sac2016' and give the container a name as 'build-env'. This image comes with all .net sdk installed and it makes sure we can build .net projects inside the container.
  2. Go inside the container & create a directory called 'app' and make it as current working directory
  3. Copy local machine's (where your docker file is residing) csproj file to the above working directory
  4. Ask .net sdk inside the container to restore any necessary nugets needed for the csproj
  5. Now after restore copy all rest files from the visual studio project (like the controller) to the working directory inside the container
  6. Now as we have all necessary project files inside the build container, execute/run a publish command to compile & publish the csproj

Hope this makes sense now :)

So same for 'RUN PHASE'.
  1. Get an image named 'microsoft/aspnetcore' created by Microsoft from hub.docker.com that has tag as '2.0.5-nanoserver-sac2016'. To run the app I only need the .net runtime.
  2. Go inside the container & create a directory called 'app' and make it as current working directory
  3. Copy all published artifacts from the 'build-env' container we prepared before to current directory
  4. Set the startup path for the api app.
A few things to notice...
Docker will automatically keep/remove wanted/unwanted containers as it keeps executing the steps above when you execute the docker build command. That's mostly for performance & time saving management perspective. If you notice I didn't copy all files first from my machine to the build container before nuget restore. I just copied the csproj first. That's also to make sure next builds (as we modify actual controller code) are fast enough. You can read more on how to split these docker steps to minimize build time etc. Also most important point is to choose right image to download from docker hub. The tag matters a lot. E.g. now i want to host this api app inside service fabric service. So we have to know that the windows server 2016 VMs (with containers) that service fabric creates by default still not upgraded to fall creator's update, so we can not use latest tag available in docker hub which is (as of today) '2.0.5-2.1.4-nanoserver-1709'. We must use tag '2.0.5-2.1.4-nanoserver-sac2016'.

So now you have the docker file you can build an image via docker build from powershell (change directory to the location where the dockerfile is created). Give it a name like 'dsanjay/quotesgenerator' and optional tag like 'latest'. There is a reason why I choose 'dsanjay/quotesgenerator' as name. It will be helpful while publishing to docker hub. You can find more details here.

docker build -t dsanjay/quotesgenerator:latest .

Once done you can execute docker images command from powershell to check that the image is created. 

docker images command
Now you have the image in your local machine. So you need to publish it to some place from where Azure Service Fabric can download or rather anyone else can download and use your app. So either you can publish to public docker hub repository or you can publish to Azure Container repository. Follow the following steps to publish to your repository. 

docker login --username sanjayd --password ************
docker push dsanjay/quotesgenerator:latest

Once uploaded you now have the image in docker hub. We can use this image to deploy our Service Fabric service. Let's do that now.

Create the containerized service in Visual Studio


The Service Fabric SDK and tools provide a service template to help you create a containerized application.
  • Start Visual Studio. Select File > New > Project.
  • Select Service Fabric application, name it "SFContainerTestApp", and click OK.
  • Select Container from the list of service templates.
  • In Image Name enter "hub.docker.com/r/dsanjay/quotesgenerator:latest", the image you pushed to your container repository.
  • Give your service a name say 'QuotesService', and click OK.

Configure Communication of the Service Fabric Service


In 'ServiceManifest.xml' file expose expose 8080 as the public port for the api app you are going to publish.
<Endpoint Name="QuotesServiceTypeEndpoint" UriScheme="http" Port="8080" Protocol="http" />

Configure container port-to-host port mapping and container-to-container discovery


In 'ApplicationManifest.xml' add a port binding between the SF Service and the container hosted inside it.

<PortBinding ContainerPort="80" EndpointRef="QuotesServiceTypeEndpoint"/>

Also just for clarity make sure the isolation mode is defined as 'process' in the policies. This is the default value.

<servicemanifestimport>
 <servicemanifestref servicemanifestname="QuotesServicePkg" servicemanifestversion="1.0.0">
  <configoverrides>
    <policies>
      <containerhostpolicies codepackageref="Code" isolation="process">
        <portbinding containerport="80" endpointref="QuotesServiceTypeEndpoint">
      </portbinding></containerhostpolicies>
    </policies>
  </configoverrides>
 </servicemanifestref>
</servicemanifestimport>

Deploy the container application

Save all your changes and build the application. To publish your application, right-click on SFContainerTestApp in Solution Explorer and select Publish.

In Connection Endpoint, enter the management endpoint for the cluster you created earlier. For example, "mycluster.westus2.cloudapp.azure.com:19000". You can find the client connection endpoint in the Overview blade for your cluster in the Azure portal.

Click Publish.

Now you can monitor your service fabric explorer to check the health status of the app you deployed. It will be in error state for some moment until SF downloads the image from docker hub & installs in the node & stars the same. Once done you can happily browse mycluster.westus2.cloudapp.azure.com:8080/api/quotes/4 to get a few quotes.

Let me know if you face any issues.

Also you can find more details in msdn.

SanjayD

Author & Editor

Just another technology enthusiast. Working on various Microsoft technologies for past 11+ years. Started from classic asp and VB and now moved on to Azure & IoT scenarios. Love to explore new ideas & concepts.

4 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. custom cbd oil boxes are printed packaging for your products. custom cbd oil packaging is designed with logo and your specification. custom cbdd oil packaging boxes are available at wholesale rates. custom cbd oil box packaging is inspiring packaging solution for your product. Get custom printed cbd oil boxes at wholesale rate with free shipping cost all across the United States and Canada.

    ReplyDelete
  3. Cigarette boxes come in a variety of layouts that will surely match your standards. Get eco-friendly cigarette boxes and enhance the fame of your brand. Cigarette boxes are being shipped worldwide free of cost so make sure your order will be placed as early as you are passionate to take the first step of your brand’s recognition.
    Custom boxes
    Cardboard Cigarette boxes
    Custom pre-roll boxes
    Cardboard box with handle

    ReplyDelete

 
biz.