Run a Precompiled .NET Core Azure Function in a Container
4 minute read
So this morning I found my self browsing through the images Microsoft has published in the Docker Hub and then I saw this one: microsoft/azure-functions-runtime and decided to Run a Precompiled .NET Core Azure Function in a Container.
Prerequisites:
Create a .NET Core lib project
Create a .NET Core lib project.
dotnet new lib --name dni
cd dni
rm .\Class1.cs
Add the required references to be able to use Azure Functions API
Be sure to add the following packages to the project. I couldn’t make the sample work with the latest versions of some of the Microsoft.AspNetCore.* packages, so pay special attention to the version parameter.
dotnet add package Microsoft.AspNetCore.Http -v 2.0.0
dotnet add package Microsoft.AspNetCore.Mvc -v 2.0.0
dotnet add package Microsoft.Azure.WebJobs -v 3.0.0-beta4
dotnet add package Microsoft.Extensions.Primitives -v 2.0.0
dotnet add package Newtonsoft.Json -v 10.0.3
Modify the Output Path of the project
Edit dni.csproj and the OutputPath property with the following value: wwwroot\bin. The project contents should now look like the following text:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<OutputPath>wwwroot\bin</OutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0" />
<PackageReference Include="Microsoft.Azure.WebJobs" Version="3.0.0-beta4" />
<PackageReference Include="Microsoft.Extensions.Primitives" Version="2.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
</ItemGroup>
</Project>
Create the wwwroot and validate folders
Create two folders. The first one wwwroot will hold all the functions and global configuration. The second one: validate will hold the configuration of the validate function we’ll be deploying.
md wwwroot
md wwwroot/validate
Create host.json file in the wwwroot folder
Create a host.json file in the wwwroot folder with the following contents:
{ }
Create function.json and run.csx files
In the wwwroot/validate folder create a functions.json file with the following contents:
{
"bindings": [
{
"authLevel": "anonymous",
"name": "req",
"type": "httpTrigger",
"direction": "in"
}
],
"scriptFile": "..//bin//netstandard2.0//dni.dll",
"entryPoint": "Dni.HttpTrigger.Run",
"disabled": false
}
Note that in functions.json we are specifying the function trigger type as httpTrigger and also specifying the scriptFile and entryPoint.
Now create a run.csx file with the following contents:
//leave this file empty - all the logic is placed within our precompiled function
Create an HttpTrigger.cs file to hold your function
Create a HttpTrigger.cs file with the following contents:
namespace Dni
{
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs.Host;
public class HttpTrigger
{
public static IActionResult Run(HttpRequest req, TraceWriter log)
{
log.Info("DNI Validation function is processing a request.");
string dni = req.Query["dni"];
return dni != null
? (ActionResult)new OkObjectResult(ValidateDNI(dni))
: new BadRequestObjectResult("Please pass a dni on the query string");
}
public static bool ValidateDNI(string dni)
{
var table = "TRWAGMYFPDXBNJZSQVHLCKE";
var foreignerDigits = new Dictionary<char, char>()
{
{ 'X', '0'},
{ 'Y', '1'},
{ 'Z', '2'}
};
var numbers = "1234567890";
var parsedDNI = dni.ToUpper();
if (parsedDNI.Length == 9)
{
var checkDigit = parsedDNI[8];
parsedDNI = parsedDNI.Remove(8);
if (foreignerDigits.ContainsKey(parsedDNI[0]))
{
parsedDNI = parsedDNI.Replace(parsedDNI[0], foreignerDigits[parsedDNI[0]]);
}
return parsedDNI.Length == parsedDNI.Where(n => numbers.Contains(n)).Count() &&
table[int.Parse(parsedDNI) % 23] == checkDigit;
}
return false;
}
}
}
Cause I didn’t want to create a simple Hello World sample, this Azure Function Code takes the dni parameter from the query string and validates if the given value is a valid Spanish National Identity Document number.
Create a dockerfile
Create a dockerfile with the following contents:
FROM microsoft/azure-functions-runtime:v2.0.0-beta1
ENV AzureWebJobsScriptRoot=/home/site/wwwroot
ADD wwwroot /home/site/wwwroot
Note that once you execute a docker build on the file all the contents of the wwwroot folder will be copied to the /home/site/wwwroot inside the image.
Build the project and the docker image
Build the .NET Core project so you get a precompiled funtion and then build the docker image:
dotnet build
docker build -t dni .
Create a container and test the function
Run the following to run the Azure Function in a container:
docker run -p 5000:80 dni
Now navigate to: http://localhost:5000/api/validate?dni=54495436H and the page should return true.
You can download all code and files here.
Hope it helps!